Posts Tagged ‘lighting’

RealKo Engine: Apply textureset with airplane

Friday, June 12th, 2009

Hey, we meet again.
I hope to come back in a while and post something in progress about my RealKo Engine.
Okay, this time I will show you the real stuff of airplane applied with diffuse/specular/normal mapp.

I have found out by myself, get the feeling that only the diffuse map is not enough in this modern day. Every models, if possible, should have all the basic textureset that is diffuse/specular/normal as the base. For other maps, it’s up to the implementation. That textureset can enhance the visual-feeling of the material for each of the different model in the game in the great amount. By combining it with the deferred shading, you can get most the visual quality (along with performance at the same time).

For what I gonna show you now is the demo scene, consists of 2 boeing classes which are Boeing 100 with master texture, and Boeing 400 with Thai Airways texture. Also with the preset 3 lights which are 1 directional light (sun light which point straight downward), and 2 pointlight which one of them is located near the airport tower, and another is located infront the tower on the runway-floor, both of point light just be a bit higher from the ground.
Note that one of the point light has Coral color, another has white color.

The demo scene demonstrates the effect of light, particles scene integrated with deferred shading process (in fact it’s just drawed after the deferred shading result), textureset applied for model (boeing in this case). And you can see other minor features by yourself in the gallery below.

Before I show you the gallery of this demo scene, let’s see the textureset applied with the airplane itself first. Just to get some feeling of how important the diffuse/specular/normal can enhance our scene and overall visualization.

Textureset applied with airplane

Diffuse Map

Diffuse Map

Specular Map

Specular Map

Normal Map

Normal Map

Those are textures used and applied with the airplane model.

Note: The reason I tell my artist to do the gray scale format for specular map for me is that, my shader code will get the data out from the specular map in one whole scalar value, not color. So by choosing the gray scale, we can just read the red channel of the map and that’s it, just furthur apply with the lighting algorithm then we’re done.

See my excerpt shader code for that part.

if(specularTextureEnabled)
{
output.Color.a = tex2D(specularSampler, input.TexCoords).r * specularIntensity;
}
else
{
output.Color.a = specularIntensity;
}

Let’s see the result of all we are talking about.

I also included a couple of images that aren’t applied with textureset.

Okay, it’s late now haaah!!
Until next time my friends.

RealKo Engine (Journal diary of working in progress)

Monday, June 8th, 2009

Everyone, I want to tell you that I have solved the problem now.

For what I have done is simple, draw particle scene on top of the deferred scene as Shawn said.
Also the external scene like particle scene in this case involves with the depth buffer, thus like MJP said, we must be aware when using all of these stuffs with XNA as the framework might tries to reset everything (I guess as I have worked on it, as if our rendering system is complex enough that requires many render targets, and we must switch between them, this might be the case that the framework tries to reset the buffer automatically. We will not face this behavior if our rendering system is just one draw call that everything is contained in it.). So we should do at most everything we can control like clearing the buffer, etc.

This is the step-pass I used
1. Prepare all the render tagets, ready for Deferred shading process.
2. Set our custom depth buffer (just to be matched in format with the depth render target used in deferred shading process) to graphics device.
3. *Clear the depth buffer to 1.0f.
4. Draw the deferred scene.
5. Unset all the render targets used in deferred shading scene.
6. Set our original depth buffer to graphics device.
7. Draw the particle scene. But remember to set our custom depth buffer to graphics device again.
8. Set back the original depth buffer to grpahics device.

*If we miss the step 6 and 7, the framework will suggest use the depth buffer which is not for us, so everything will not be as our expect.

See the following code, cut from my DeferredShadingRenderer class,

///
        /// Prepare the deferred rendering process.
        ///
        /// Draw part will be handled by the outside.
        ///
 
        public void BeginDraw(GameTime gameTime)
        {
            //set the proper depth-test function
            graphicsDevice.RenderState.DepthBufferFunction = CompareFunction.LessEqual; 
 
            //set render targets
            SetGBuffer(); 
 
            //cache the current depth buffer
            old = graphicsDevice.DepthStencilBuffer;
            //set our custom depth buffer
            graphicsDevice.DepthStencilBuffer = depthBuffer; 
 
            //clear render targets
            ClearGBuffer(); 
 
            //clear out our depth buffer
            graphicsDevice.Clear(ClearOptions.DepthBuffer, Color.Black, 1.0f, 1);
        }

And another one.

        ///
        /// End the deferred rendering process.
        /// In fact, end draw will finish the deferred rendering pass by drawing the lights, and draw scene with or without bloom post-processing.
        ///
        /// Draw part will be handled by the outside.
        ///
 
        public void EndDraw(GameTime gameTime)
        { 
 
            //resolve all render targets
            ResolveGBufer(); 
 
            //set the depth buffer back to old one
            graphicsDevice.DepthStencilBuffer = old; 
 
            //draw all lights
            DrawLights(gameTime); 
 
            //draw on top of the result from lighting target
            graphicsDevice.SetRenderTarget(0, combinedLightRt); 
 
            //set to use our custome depth buffer
            graphicsDevice.DepthStencilBuffer = depthBuffer; 
 
            //Note: All the particle systems should be drawed after all the solid objects are drawed. This is quite important as the particle itself
            //can be able to pass the depth-test.
            //draw the particle system
            //TODO: Add any related functionality into this drawing section of particle systems.
            if (ParticleSystemsManager.NumberOfParticleSystem > 0)
            {
                //traverse all the particle system
                foreach (ParticleSystem p in ParticleSystemsManager.ParticleSystems)
                {
                    //draw
                    p.Draw(gameTime);
                }
            }
            //ENDTODO 
 
            graphicsDevice.SetRenderTarget(0, null); 
 
            //set the depth buffer back to old one
            graphicsDevice.DepthStencilBuffer = old; 
 
            //draw the bloom applied, or just normal scene
            if(isBloomApplied)
                DrawPostProcessing(gameTime);
            else
                DrawNormalScene(gameTime);
        }

As you see above, I have 2 methods to be used in drawing process. Other scenes will be drawed in between those 2 methods.
Hope this will clear out some points.

The last word as I learned from this exprerience => DO NOT INVOLVE ALPHA BLENDING STUFF DURING DEFERRED SHADING PROCESS.

Thanks Shawn, and MJP for your great help that can point me to this final clue.

And this is the result.

Alpha in deferred fixed

Alpha in deferred fixed

Note: You can see similar post, that I have posted out in creator clubs here.

Lighting 2D

Wednesday, May 13th, 2009

Have you ever wonder how to implement the lighting in the cloudy and raining day?
For me, the answer is “yes”. By jump across directly to 3d world would be a bit of difficulty, so I decide to do it in 2d first.

The behavior of the lighting in natural is complex and unpredictable, we always try to simulate those behavior in the term of graphics programing. By using the recurrsive routine to help out, we can achieve at least the close one.

Only 2 main parts to implement this thing.
First is LineDrawer, and Second is Algorithm to simulate the lighting.

Why bother do the line drawer system, isn’t it exist already in xna framework? No.
Actually the pixel drawer in XNA also doesn’t exist, but we can work around this which I will explain how to do it next.

For pixel drawer in XNA, you have to create the 1 x 1 pixel texture of white in order to be used as the texture to draw on screen. Of course, the white choosed is important, as we can tint it with other color. Thus giving us ability to draw 1 pixel color on screen.

But for line, how can we do that?
We also use the concept of pixel drawing.
Imagine you want to draw line, thus we have to put those pixels (thus 1×1 texture)  in sequence from (say) point A to point B on screen. That’s it, we just iterate the process and draw each loop with that 1×1 texture.
But with this approach we need to calculate the position for each of the texture being drawed, and lots of textures too, nonetheless it gives the most accurate of line (we may not see the different).

So what we will use instead is that, we will use only 1×1 texture for each pair of point defined the line.
We will stretch it along the x-axis for the magnitude after we know the distance between two points, and we will stretch along the y-axis for our variable line-thickness. Also we will rotate the texture too, in the case if two points are not on the same horizontal.

You can see all of this in PrimitiveLine.cs file. (The download link is below, thanks for the author for this great and very useful line drawer, I’m sorry that I can’t remember the name because it’s very long ago.)

The most notable part is here.

        ///
        /// /// Renders the primtive line object.
        /// ///
        /// ///The sprite batch to use to render the primitive line object.
        public void Render(SpriteBatch spriteBatch)
        {
            if (vectors.Count < 2)
            return;            
 
            for (int i = 1; i < vectors.Count; i++)
            {
                Vector2 vector1 = (Vector2)vectors[i-1];
                Vector2 vector2 = (Vector2)vectors[i];               
 
                //check for boundary
                //we dont draw anything if both vertexes are out of range
                if ((vector1.X < 0 && vector2.X < 0) ||
                   (vector1.X > width && vector2.X > width))
                    return;
 
                // calculate the distance between the two vectors
                float distance = Vector2.Distance(vector1, vector2);
                // calculate the angle between the two vectors
                float angle = (float)Math.Atan2((double)(vector2.Y - vector1.Y),
                    (double)(vector2.X - vector1.X));
                // stretch the pixel between the two vectors
                spriteBatch.Draw(pixel,
                    Position + vector1,
                    null,
                    Colour,
                    angle,
                    Vector2.Zero,
                    new Vector2(distance, Thickness),
                    SpriteEffects.None,
                    Depth);
            }
        }

Okay, let’s we move to the algorithm itself to simulate the lighting.

Two points defined a line

Two points defined a line

We will use the recurrsive approach here, as you see from the image above, two points defined a line.
Then if we find its middle-point, and offset its position at random for a little, and repeat this step until the length between the end point to mid point is small enough, then we will get the simulated lighting.

See it here (in Game.cs),

/// 
        /// Add the vertices to the lighting between the two end points a, and b.
        /// 
        ///
 
        ///
 
        ///
 
        private void AddLightingVertices(Vector2 a, Vector2 b, float displacement, int lindex)
        {
            if (displacement < CURR_DETAIL)
            {
                //add the two end points
                lineDrawer[lindex].AddVector(a);
                lineDrawer[lindex].AddVector(b);
            }
            else
            {
                //calculate the midpoint between point a, and b
                float mid_x = (a.X + b.X) / 2.0f;
                float mid_y = (a.Y + b.Y) / 2.0f;
 
                //displace it a little
                mid_x += ((float)random.NextDouble() - 0.5f) * displacement;
                mid_y += ((float)random.NextDouble() - 0.5f) * displacement;
 
                Vector2 midPoint = new Vector2(mid_x, mid_y);
 
                //draw the line from two end points to the mid point
                AddLightingVertices(a, midPoint, displacement / 2, lindex);
                AddLightingVertices(midPoint, b, displacement / 2, lindex);
            }
        }

After this finishes you will get all the vertices ready to be drawed by line drawer.
Notice that I want the code for drawing to be clean as possible (like drawing the point at the leftmost to the rightmost), so each two end-points of lighting requires one PrimitiveLine to handle it.
Thus if you increase the number of bolt, then you need to increase the PrimitiveLine too.

Now you are ready to draw it,

protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.Black);
 
            //early start of the spritebatch (to get the benefit of only one traversing of loop)
            spriteBatch.Begin(SpriteBlendMode.None, SpriteSortMode.Immediate, SaveStateMode.None);
 
            //loop through all the line of the lighting
            for (int i = 0; i < NUM_BOLT; i++)
            {
                lineDrawer[i].ClearVectors();
 
                //add the point to the lighting
                AddLightingVertices(a, b, DISPLACEMENT, i);
 
                //render the lighting
                lineDrawer[i].Render(spriteBatch);
            }
 
            spriteBatch.End();
 
            //Draw the info text
            DrawInfoText(gameTime);
 
            base.Draw(gameTime);
        }

I just want to use each loop efficiently so after I add the vertices for each pair of bolt then I draw it immediately as you see above.

You’re done for this, note that you can add more settings for this app, like the number of bolt, the threshold length (to stop the recurrsive, note that for this I named it “Detail”), the displacement for the midpoint to be offset away from the line, thickness of the line.

Here is the result,
(Sorry for my quite mess post, it’s very late now, and I should go to sleep, sorry for that folks.)

Lighting 2D: Download