Archive for May, 2009

Integrate Creator Club’s particle system into deferred shading system.

Tuesday, May 26th, 2009

From what I have done now, integrating the particle system from creator club into my deferred shading system. I have 2 options as this case also can be applied to you too for the approaches I gonna use to integrate this stuff.

First, it’s the simplest one which can be done without much effect. NO modifications are need for ParticleEffect.fx file of the particle system, thus giving you the most comfortable one. What the first one does exactly? Well it does render the particle scene on top of the finished deferred scene by just combining their textures. In this way, although the work is well reduced, but the particles still visible through the solid objects. Thus it the early simple work now comes to the cumbersome, in which you much get the depth buffer from deferred scene, whether or not it comes from your render target or the graphics device’s current depth buffer. We use it to just occlude the particles that must not be seen if they are behind our objects in deferred scene. Also, this is not enough if we choose not to modify any part of the ParticleEffect.fx file, then we must get particle scene’s depth buffer out too. In conclusion, we need two more textures of depth buffer externally from the ParticleEffect.fx to correctly draw the particles on screen, and thus another effect to combine them so more passes required for the final scene. But if we choose to modify some parts of that file, we need to calculate the location of the depth buffer to sample the depth at the particular position of a single particle. Compare them and then correctly draw. Yes, I think it can be called the nice way too. But this is not the approach I will use, as I want the overall rendering pass to not be increased anymore.

Second approach, this is what the approach I chose. The reason is to reduce as much the render pass for my rendering system. It requires no additional rendering pass at all, as it will now become the part of the deferred shading itself. For what I done with this approach is this, I have treated the particle scene as the normal scene for deferred shading. It can be called for updating, and drawing like the normal scene existed in deferred pass. In this way, we reduce at much the overhead to switch between the effect, and time to produce the final scene.

How to do it? I have to add some codes into the ParticleEffect.fx file.

The following is the list for my addtion to the code. List of  addition
1.  add the copy of transformed position (vector4) for vertex output structure => we only do the calculatation for depth value here

2.  add the receiving parameter (corresponding to 1.)

3.  add the output of pixel shader structure, writes to all the related and only neccessary render target

4. add the part of code inside pixel shader to write the output.

Let’s see the real action below

We must add the copy of transformed position (vector4) into the vertex output, thus we can store our particle’s depth into the depth render target, thus this will solve our “particle through solid object” problem.

struct VertexShaderOutput
{
    float4 Position : POSITION0;
    float Size : PSIZE0;
    float4 Color : COLOR0;
    float4 Rotation : COLOR1;
    float4 CopyPosition: TEXCOORD0;
};

Note above that we use TEXCOORD0 semantic to hold our data. And now take a look at the vertex shader function, as we will add single line to copy the transformed position (vector4) and route it to the output. See below

// Custom vertex shader animates particles entirely on the GPU.
VertexShaderOutput VertexShader(VertexShaderInput input)
{
    VertexShaderOutput output;
 
    // Compute the age of the particle.
    float age = CurrentTime - input.Time;
 
    // Apply a random factor to make different particles age at different rates.
    age *= 1 + input.Random.x * DurationRandomness;
 
    // Normalize the age into the range zero to one.
    float normalizedAge = saturate(age / Duration);
 
    // Compute the particle position, size, color, and rotation.
    output.Position = ComputeParticlePosition(input.Position, input.Velocity,
                                              age, normalizedAge);
 
    output.Size = ComputeParticleSize(output.Position, input.Random.y, normalizedAge);
    output.Color = ComputeParticleColor(output.Position, input.Random.z, normalizedAge);
    output.Rotation = ComputeParticleRotation(input.Random.w, age);
    output.CopyPosition = output.Position;
 
    return output;
}

See the line “output.CopyPosition = output.Position”. Isn’t it simple? Now we move to the pixel shader part. But before moving into it, I must tell you what about my GBuffer layout first, so you can adapt it into your own and work correctly.

For my layout, I have 4 render targets as follow

RT1, Color  (ARGB with 8 bit pixel format  for each channel), this render target just contain the albedo color
RT2
, Depth t (32 bit float format using 32 bit for red channel), this render target contains pure depth value
RT3,
LightOcclusion (same format as RT2), this render target contains information about whether or not the light will lit each pixel (for example the skydome, you dont want to light it, so settings this value to 1 to disable light effect when drawing skydome.)
RT4,
Normal (same format as RT1), in fact you can use 16-bit for x and y, then calculate z using 1 - x^2 - y^2.

Okay, let’s see the code

struct PixelShaderOutput
{
	float4 Color: COLOR0;
	float4 Depth: COLOR1;
	float4 LightOcclusion: COLOR2;
};

You may ask at this point. Why I don’t include the normal as output in this structure? Because the hlsl rule, as when you include the output part inside the structure, you must write it too, whether or not you do not want to be messed with its value. Thus as you may expect, I rearrange the order or render target just to take the normal to the last and not include it in the output structure, as I don’t want to modify its current value in the buffer. Because of we don’t want any one of the particle to affect the lighting calculation at the later stage, so do not mess with the current normal resided in the buffer already. Leaving this way, the lighting will not concern about the existence of individual particle. (But at the later you will see that I have set the value of lightOcclusion to 0, contradict to what I have told you, it’s because if we turn off the lighting effect on individual particle in which that particle already draw on top of our normal scene, we will see the square of pure albedo color. Thus if your scene is in night, then your rain particle system is enabled, you will see the bright square everywhere which again not what we want.) Now let’s have a look about input structure, and its pixel shader function (separate for the type of output, as you will learn that the particle system created from creators club is well implemented. The type includes “Non rotating particle”, and “Rotating particle” version).

For non-rotating version.

// Pixel shader input structure for particles that do not rotate.
struct NonRotatingPixelShaderInput
{
    float4 Color : COLOR0;
 
#ifdef XBOX
    float2 TextureCoordinate : SPRITETEXCOORD;
#else
    float2 TextureCoordinate : TEXCOORD0;
#endif
 
    float4 CopyPosition: TEXCOORD1;
};
 
// Pixel shader for drawing particles that do not rotate.
PixelShaderOutput NonRotatingPixelShader(NonRotatingPixelShaderInput input)
{
	PixelShaderOutput output;
 
	//write to the GBuffer
        output.Color = tex2D(Sampler, input.TextureCoordinate) * input.Color;
	output.Depth = input.CopyPosition.z / input.CopyPosition.w;
	output.LightOcclusion = 0;
 
	return output;
}

For rotating version

// Pixel shader input structure for particles that can rotate.
struct RotatingPixelShaderInput
{
    float4 Color : COLOR0;
    float4 Rotation : COLOR1;
 
#ifdef XBOX
    float2 TextureCoordinate : SPRITETEXCOORD;
#else
    float2 TextureCoordinate : TEXCOORD0;
#endif
 
    float4 CopyPosition: TEXCOORD1;
};
 
// Pixel shader for drawing particles that can rotate. It is not actually
// possible to rotate a point sprite, so instead we rotate our texture
// coordinates. Leaving the sprite the regular way up but rotating the
// texture has the exact same effect as if we were able to rotate the
// point sprite itself.
PixelShaderOutput RotatingPixelShader(RotatingPixelShaderInput input)
{
    PixelShaderOutput output;
 
    float2 textureCoordinate = input.TextureCoordinate;
 
    // We want to rotate around the middle of the particle, not the origin,
    // so we offset the texture coordinate accordingly.
    textureCoordinate -= 0.5;
 
    // Apply the rotation matrix, after rescaling it back from the packed
    // color interpolator format into a full -1 to 1 range.
    float4 rotation = input.Rotation * 2 - 1;
 
    textureCoordinate = mul(textureCoordinate, float2x2(rotation));
 
    // Point sprites are squares. So are textures. When we rotate one square
    // inside another square, the corners of the texture will go past the
    // edge of the point sprite and get clipped. To avoid this, we scale
    // our texture coordinates to make sure the entire square can be rotated
    // inside the point sprite without any clipping.
    textureCoordinate *= sqrt(2);
 
    // Undo the offset used to control the rotation origin.
    textureCoordinate += 0.5;
 
    //write to the GBuffer
    output.Color = tex2D(Sampler, textureCoordinate) * input.Color;
    output.Depth = input.CopyPosition.z / input.CopyPosition.w;
    output.LightOcclusion = 0;
 
    return output;
}

Now, we have done it.
For all the detail I described to you so far. I have done integrated it into my RealKo Engine.
I open for your suggestion and comment about the approach I made, you can suggest the better way to do it. Thus note for my designing, I chose the one that is not that too much difficult to implement, and does not require too much time (with close to deadline of my project), thus all they have come to be the way as I explained to you so far.

Farewell for now, and see you next time.

RealKo Engine (raining in action)

Sunday, May 24th, 2009

I have uploaded the video to show one of the weather feature of the engine to youtube.
Sorry for the quality of video, I want it to be as small as possible, and also this is my first time for uploading this stuff.

Please compared this to the following captured screenshot directly from my computer, the quality of video format is well hide my rain !!

Raining in action

Raining in action

It’s more to come.
Anyway thanks for watching.

RealKo Engine diary journal (lightOcclusion concern)

Sunday, May 24th, 2009

Deferred shading rendering system is what the system that I integrated and used as the main building block for my “RealKo Engine”.

Okay, just go straight to what I want to say now.
I have found the problem of lighting when I used deferred shading as the rendering system. I knew that all the geometry information is written to the rendertarget before any lighting calculation can take place. This concern didn’t not come to be realized when that time I am doing this, haha.

For what I want to say is that, when that time comes, the time that you want to lit the object, and select some objects not to be lit as well, how can we do it in the deferred shading, as the lighting calculation is the last pass.

Ohh, as I said above, it just comes to be relized at very late. You also need to store the information in the pre-pass, that tell the deferred shading about what pixel gonna be lit, and not to be lit => I called it “LightOcclusion”.

At very first my GBuffer layout has only 3 render targets (the same approach as Catalin Zima provided in http://www.ziggyware.com/readarticle.php?article_id=155), when I found this problem, that forces me to add in another render target. Also I have designed my each of rendertarget to contain 32 bit (RGBA), when combined all the 4, with the resolution of 1280 * 1024, I come across at exactly 20 MB (in fact should be added with another related issue too, such as Depth Buffer). That’s not quite high so far, because I have seen the one implemented in KillZone, it’s about 36 MB, so I think to myself, okay as long as we are low enough on size, we might get the speed with some close enough quality of graphics (as far as I concern, I think I come to the right track).

So by adding another rendertarget into use, I have increased it more 5 MB. The overhead of buffer need to be transfer and read/write is the big problem in deferred shading, but as long as your graphics card has enough bandwidth, that’s not gonna be a problem, as for me, GTX 275 is the beast!!!

Okay, enough for now, I will updated along when I have done some important component of the engine in the upcoming week.

Last word for today, do not forget about lightOcclusion in deferred shading.  (I can’t think of other solution to not lit some objects in the world by not use lightOcclusion, if you know some alternative just let me know here, it will be appreciated.)

RealKo Engine (Early working in progress)

Tuesday, May 19th, 2009

I have buried myself with RealKo Engine, it’s the engine to be worked with the airport-tower communication, to practice the guys out there for the real simulation when the plane take in or off.

I have started this project about 2 months ago, nearly 2 months I have spend the time to test the individual features of the engine, ranges from shading stuff, integrated the app with win-form, particle system, post processing like bloom effect, deferred shading, xml config file format, and simple network stuff, etc. Some of them may not be the feature of the final engine, but nevertheless at least I have given a try to it.

I work alongside with my artist, P.Yod, who helps me out the entire graphics resource. His works are absolutely fantastic, you will see below.

My job is to integrate all the resource and blend it down into the real working part that can be used with minimum effort from the user, thus come to this RealKo Engine.

I posted some of the working in progress screen shots below.
Some of them are drawed with the bloom post-processing pass. But all of them powered by the deferred shading render system.

Until next time firends. ;)

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