Visited Aeronautical Radio of Thailand

I visited Aeronautical Radio of Thailand or AeroThai a couple of days ago. The purpose of visiting is to getting feedbacks and reviews from my work “RealKo”.

The first version of “RealKo” was actually finished in 2009 taking time around 3 months. That time was for Suvarnabhumi Airport. Currently, the framework supports another airport model which is Yangon Internation Airport. In fact, it can support any airport models, it’s just up to model creator to feed the framework.

This visiting is quite interesting as I will have a chance for the first time seeing how far and how they use the work in real situation. I saw an actual place dedicated to tower control training. It’s located near the tall tower control in Suvarnabhumi Airport, and Yes! it’s restricted area as usual.

A plus is that a group from Myanmar who also is currently using this framework as well came to give us their comments themselves. I would rather give a big craps to AeroThai guys which are able to explore the market of making profit from the framework itself to the nearby countries. It’s not just only local!

See below of some shots I took from the place I visited.

A training room with projectors to project view from within the framework.

A training room filled with 8 projectors to project out different views from different angles of camera from within the framework itself. Staffs can sit in and train their communication skill on tower control system, and play through with the framework with their co-workers and pilots outside the room.

My team (contracting company and me), AeroThai group, and guys from Myanmar were discussing their comments for what to be fixed/added/removed. You can see some views projected on the wall now.

I am amazed on how AeroThai staffs extend the use of my work ahead. I can see a simulation of an airplane taking off the runway. At least I know now that it works out really well.

And the last one for panorama shot to get some feeling of surrounding view.

That’s all for an update for what recently I’ve been up to. Now, I got a couple of minor fixes / enhancement in hands. I’m ready to do some work.

Til next time.

posted 2 days ago

Blend it well - Skydome’s contact point with Scene

From my previous post which I mentioned to write about a simple technique I implemented and used in parallel with fog rendering system in order to pull out every sense of what’s “right” out of the screen, so here we go.

The problem usually arises when there’re models or meshes placed on a large flat plane in which a skydome covers entirely of those. What’s matter is the plane or ground as it interfaces with skydome and produces unpleasant result as seen far away in sight. It’s too separated and cut off. The artifact is easier to be seen if there’s not enough objects to distract us from glancing at the line itself. See below.

The red arrows show what happens to be a problem which we’re trying to solve.

So I came across with a simple approach to make a skydome blended well with the scene interfacing with it.

I jotted down the idea on paper, and decided to share it below for some pleasure in seeing original writing.

The main point is at the center of the page. There might be a hard time to clearly see it so I rewrote it (somewhat) cleanly below.

We have a skydome covering all of the whole scene with its both side of edges may go deep down below and pass through the ground itself. To better blend the color along the line, it should not happen to be a sudden full 100% color from the skydome’s texture right away, but it should merely smooth out for better transition from normal scene to skydome.

Height is the estimated length to do linear color blending with fog color (or fixed color value). If y-position is outside this range, then we ignore it. Min is the position where skydome texture takes all the majority of the result blending color. Max is the position where fog color (or fixed color value) takes all the majority of the result blending color. So in between, we have a linear transition.

The following is a section of hlsl code inside an effect file.

...
// blend with scene
if(input.WorldPosition.y <  SKYDOME_LS_HEIGHT)
{
        float f = input.WorldPosition.y / SKYDOME_LS_HEIGHT;
        if(fogEnabled)
        {
                blendedColor = f * blendedColor + (1-f)*fogColor*ambientLight;
        }
        else
        {
                blendedColor = f * blendedColor + (1-f)*float4(1.0f, 1.0f, 1.0f, 1.0f)*ambientLight;
        }
}
...

Note here that SKYDOME_LS_HEIGHT is HEIGHT as explained above. f is a percentage describing how much skydome’s texture color will have majority in result blending color.

Whenever fog is enabled, then we blend skydome’s texture color with fog color. I also take a consideration on global light intensity percentage (0.0 - 1.0) or ambientLight here. As I use a value to represent the sunlight intensity at particular of time to simulate my day-night effect, so I must take it into account as well.

But when fog is not enabled, then I normally blend it with white color. White color is naturally used to give out a shading level of a target color in blending operation. In additional, I want to keep a sanity in color and not to mess it up. Using white will preserve the color coming from skydome’s texture.

This section of code should be added after a main color operation is carried out, but before alpha-channel color operation will be performed (to ensure we won’t mess up with alpha value). In fact, putting this code into a separate function is also a way to go, but as I want to reduce overhead, so I can live with that.

See the comparison between turning on/off of this technique while fog is enabled below (click on image for original resolution).

That’s it for now. Til next time.

posted 3 weeks ago

Fog Fog Fog

Begin with story
I remembered back in a day that I’ve failed in adding fog in my new ground deferred shading. So I decided to pursue another route just for survival alternative, and that was particle fog.

Particle Fog

The time passed, and someone popped up a need to fully take control of fog system. Then that thing heads back and bangs me to the code!

I have done fog in shading sense before. But that time with normal forward rendering technique. So it’s quite straight forward as merely no other big stuff to be considered and would block out the way. It should be something, I always think to myself, that I miss it out in that time. Finally, I go back to Castle Wolfenstein!!

In fact, it’s a same same approach that be done inside effect file with shading programming. I would guess that because I saw everything shaded into white, then I suddenly gave up.

Wait! What’s wrong with particle fog?

Particle system can be implemented in 2 major ways.

  1. Triangle or Quad-based
  2. Point sprite

My current particle system uses a 2nd approach.

The resource needed for point sprite to represent one particle is one vertice compared to another way which may need 3 or 4 vertices based on technique of implementation. So it’s ideal to have point sprite in place for particle system as number of particles surely will be high. But it comes into some costs as well.

Firstly, Point sprite will be scaled up/down based on the distance to the camera. Thus whenever we go closer and closer, the particle (or point sprite) will be really small so we won’t be able to see nice detail of the particle itself. Consider that a building catches on fire. Far away, you clearly see its effect and recognize that it’s fire. But when you come closer, particles get smaller and smaller til you see the house itself which seems like nothing has done anything to it.

Secondly, in fact both of the approaches, it’s harder to control behavior of particle system although you have a good tool to simulate the behaviors and it acts like that in the real simulation. I believe for most hands-on code in purity, if it’s not designed to be a tool, it will have to be manually adjusted in terms of particle’s position, number of particles, direction it goes, size, randomness stuff, etc.

It would conclude that I should stay away from point sprite (in case of fog effect), and use triangle / quad - based instead. Anyway, a better approach is to use shader. This way we gain all control for whenever to do shading, fog’s settings in terms of density or anything else, and the most importantly, it’s uniform on the whole screen buffer.

Side-note: Shawn Hargreaves stated in his post that point sprite won’t be supported in XNA 4.0. DirectX 10 and 11 will cut out its future from there as triangle / quad - baseds is proved to be as efficient and sometime better than point sprite approach.

Okay, here the things

Each individual entity has its own effect (or shader) file that describes how to render itself on screen. Surely, every of my shader files include one common include-file where inside has basic operations in both terms of transformation, and pixel shading that they can use and adapt up on to more specific operation.

Fog related variables lie inside that include-file. The following is HLSL language declares fog related variables as shared ones across all shader files as I want fog to be globally effect. Just set its settings once, then every single entity, every mesh in simulation will be rendered with consideration of fog shading.

// -- Fog properties --
// Linear Fog
shared float fogNear;
shared float fogFar;
shared float fogAltitudeScale;
shared float fogThinning;
// Exponential Fog
shared float fogDensity;
// Others
shared float4 fogColor;
shared bool fogEnabled;
shared int fogFormulae;	// 1 = LINEAR FOG, 2 = Exponential Fog, 3 = Exponential Fog ^ 2
shared const float E_CONST = 2.71828;

To be more elaborate on the above variables, I researched through the Internet and found this one. Its information dated back in time of DirectX 9, but the theory still holds. A notable graph comparison at the bottom is really nice and blowing benefit.

I decided to implement them all for 3 types of fog which are Linear, Exponential 1 and 2. That graph tells everything! Whenever you want any other behavior of fog, you compare them and choose what’s right for you.

// Linear Fog
float4 LinearFogPS(float4 color, float3 worldPosition)
{
    float d = length(worldPosition - cameraPosition);    
    float l = saturate((d - fogNear) / (fogFar - fogNear) / clamp(worldPosition.y / fogAltitudeScale + 1, 1, fogThinning));
    
    return lerp(color, fogColor, l);
}

// Exponential Fog
float4 ExpoFogPS(float4 color, float3 worldPosition)
{
        float f = pow(E_CONST, length(worldPosition - cameraPosition) * fogDensity);
        f = 1.0 / f;
        return saturate(f * color + (1-f) * fogColor);
}

// Exponential 2 Fog
float4 Expo2FogPS(float4 color, float3 worldPosition)
{
        float f = pow(E_CONST, pow(length(worldPosition - cameraPosition) * fogDensity, 2));
        f = 1.0 / f;
        return saturate(f * color + (1-f) * fogColor);
}

saturate() is added for sane of color stability. Note f*color + (1-f)*fogColor that merely explains the essential of f by means of “how much should color should be seen after combined with fog color”. This is why Maths is so lovely in hidden message, it won’t directly speak in normal human language but instead purity of its own tradition.

fogFormulae will be a key for us as I will allow users or whoever uses my framework to be able to instantly change the method to calculate fog on-the-fly. Thus I wrote a handy function just to check for which way to calculate for fog. This function will be used across shader files.

float4 fogFormulaePS(float4 color, float3 worldPosition)
{
        if(fogFormulae == 1)
                return LinearFogPS(color, worldPosition);
        else if(fogFormulae == 2)
                return ExpoFogPS(color, worldPosition);
        else if(fogFormulae == 3)
                return Expo2FogPS(color, worldPosition);
        else
                return color;
}

This means that caller has a sole responsibility to send-in forFormulae value into shader file as well as other related fog variables. But as long as they don’t frequently change the fog setting, they just have to do it once and for all.

Now, we already set things up.

Just a side-note for myself, an include-file is going bigger and bigger. Once only pixel shader model (PS Model) version 2 is a way to go, but as things go bigger, I have to change it to version 3. This is a two-sword decision. It would cut users who use PS v2 capable graphics card, and target only for those who use PS v3 and above. Anyway, think it in a positive way, as my framework is bandwidth hunger, setting it to PS v3 will told the requirement for any system to run it in the first place. Misunderstand and self-thinking would not happen.

Now, it’saa bout time!

So it’s time to make use of the things we already set up previously. I excerpted the code inside airport’s shader file of pixel shader function to let you see how we take the code into a real production.

RenderGBufferPixelOutput RenderGBufferPS(RenderGBufferPixelInput input)
{
        RenderGBufferPixelOutput output;

        //Color
        //Lerping base and target texture
        //get color from baseTexture
        float4 baseColor = tex2D(baseSampler, input.TexCoords);
        //get color from targetTexture
        float4 targetColor = tex2D(targetSampler, input.TexCoords);

        //lerp from baseTexture to targetTexture (the dTime must be set properly)
        float4 blendedColor = lerp(baseColor, targetColor, dtTime);
        
        // fog
        if(fogEnabled)
                blendedColor = fogFormulaePS(blendedColor, input.WorldPosition);

        ...
        // do whatever you like here
        ...

Not to worry about why I do lerping here. I have 3 different weathers so there’s some chance that some parts of airport would do lerping from normal weather texture to snow weather texture.

Line to note is commented out with “// fog”. We just test it whether at the moment fog is enabled to apply or not, if so then we use our handy function to handle decision over calculating fog on each pixel whether it’s Linear, Exponential 1 or 2. We plug in the color, and its world position.

See the result

See the full gallery below of what the result may look like. I reserve the space to the next post for another simple technique I implemented in parallel to fog (as in my case) in order to make it looks much better along the edge of the ground map interfacing with skydome.

Til next time.

posted 4 weeks ago

Goodies!

Finished updating some enhancement to RealKo framework, and this for April.

posted 1 month ago

DLAA and do it in post-processing

For a long time that I think to myself, the only way to add anti-aliasing ability into deferred shading renderer is to mess around among its steps which involve some kind of tedious tasks, rerouting and higher maths stuff. So I haven’t taken a look at this seriously until someone popped up this issue again and I have an enough gap to make it done. Then it’s time …

Anti-aliasing in normal rendering environment can be enabled via toggling a flag telling a hardware to do that for you. But when deferred shading is in place, that thing is not supported. You have to do it yourself.

The whole idea I started with is “how we can do this in post-processing”, if that’s possible at all? The fact that I don’t want to mess around among important steps of deferred shading to add another ability. If we could, do it outside the box separately is a good way to go. At least, if something happens we know where it comes from.

I found a starting point here. I remember I went back and forth with that link for several times. A reason that S.T.A.L.K.E.R was the very first to implement deferred shading already prove for a gogo that AA would be possible. Nonetheless, I don’t fully understand the code at the first read. It requires readers to assume something, and make something available before apply the code fully. Then I found this. A very interesting idea came from the guy in forum named “Styves”. He seemed to found or create a new adaptation of AA as post-processing technique for deferred shading which works quite well with jungle environment with lot of short edges showing on the screen. The basic idea is to calculate the difference between color space of pixels around the center (in pattern). Then form normal to represent the direction that should be for the that particular position of edge. Finally, get the color samples up again with the perturbation of texture coordinate from newly calculated “normal” representing each pixel, in order to sum them up and give out a final color. Unfortunately, this technique don’t work with my engine. It gave out not acceptable result, merely the same as NO AA.

Continued searching, and I found this one. Another technique called DLAA (DirectionaL Anti-Aliasing) which is used in Star Wars : Force Unleashed II. I personally think that the idea is similar for most of AA as post-processing here. The main differences come from how we approach to find edges, and additional specific steps. It may need more samples, with weird patterns, and some higher maths if need. I added DLAA as a post-processing into my RealKo engine, the result is decent. Much better than previously, things get a little bit more blurry but jaggy edges are gone. But in a certain angle, it can’t 100% solve the problem but just reduce it.

DLAA takes 2 passes. First pass is used to create edge representation image that will be used as input for the next pass.

In fact, the first pass just marked the edge of all pixel in the input image (which is the final combined with light resulting from deferred shading’s process). The clever portion of code which I liked the most is that it actually marks the edge for each pixel and stores that piece of information via alpha-channel of the input image itself. This cuts a need to temporary render target to hold a result from Pass 1. So we can draw the result direct to back buffer, and Pass 2 just continues using it as an input. Anyway, I don’t use this benefit as I may have to use a result from deferred shading again. So I won’t mess things up with it, and insist to create additional render target to hold the result.

Then it comes the second pass. This pass will operates on edge data produced from the first pass. It then measures for short edge, and (if need) long edge. It do several calculations to create data in order to get amount of blur to finally applies to result pixel.

Short note: Due to its several instructions required, SM (shader model) version 3 (at least) is needed. Thus it breaks my SM 2.0 for this ability especially.

See some shots below (click on image for original size).

As mentioned, I doubt that there always will be some certain angles that AA can’t solve? Please take a look at the first pair of screen shots. The position of camera is on the tower looking towards the runway in a far sight. We partially see some white swapping with gray color in both edge of runway, and it rather seems we can do something about this.

Anyway, anyhow, at least a decent AA already did it jobs here: Reducing jaggies.

Keep rolling …

posted 1 month ago