Lightning Sample

This sample shows an implementation of lightning rendering in XNA GS 2.0

The technique and math is based on a DirectX10 sample made by NVIDIA. Since the NVIDIA sample was made for DirectX10, I had to move most of the simulation on the CPU.

A GPU simulation can also be done, but it would need means of getting random numbers in the vertex shader. To do this, you can either use shader constants (though these give a limited range or numbers), or store them inside vertex textures. For this sample, I chose to stick to the CPU implementation, so the sample can be run by any PC owning a SM 2.0 video card.

The effect is very customizable. The LightningBolt class (looking back at this, I might have chosen a better name) takes as a constructor parameter an instance of LightningDescriptor. This LightningDescriptor contains a bunch of parameters that may be customized in order to obtain different shapes, appearances and behaviours for the lightning effects.

One of the most important parameters is the topology, which is a list of operations that will be recursively applied on the lightning segments to obtain the lightning shape. These operations may be either Jitter (which takes a point on the segment and displaces it), or JitterAndFork (which also creates a new segment starting from the displaced points, towards a random point near the original segment).

To see how these affect the lightning, please try and experiment with different settings.

The sample includes 4 examples of such usages: lightning, energy bolt, graffiti-like shape, and wormy-laser-shape :).

lightningelecticity

graffitti worm_laser

When running the sample, use the following controls:

Cycle through examples: Gamepad A / Keyboard Space

Toggle Background: Gamepad B / Keyboard B

Freeze Animation: Gamepad Y / Keyboard F

Exit Sample : Gamepad Back / Keyboard Escape

The sample source code can be downloaded here: Lightning Sample.

  • Pingback: Catalin Zima - XNA and HLSL blog » March Sample released: Lightning Sample

  • http://nick.gravelyn.com Nick

    That is really cool. I can’t wait to get home and play with it.

  • http://amapplease.blogspot.com Pete

    Downloading it now … c’mon c’mon … hurry up!

  • http://amapplease.blogspot.com Pete

    Wow, great visual effects!

  • http://nick.gravelyn.com Nick

    Great stuff! One question though: why did you turn off fixed time step and syncing with vertical retrace? That caused some awful tearing on my machine. I re-enabled both and it still ran great. Any particular reason?

  • http://www.catalinzima.com Catalin Zima

    No particular reason.
    I just disabled them so I could test the framerate of some configurations one last time, and forgot to re-enable them.

  • http://www.catalinzima.com Catalin Zima

    I uploaded the modified version. Thanks, Nick for pointing it out.

  • http://nick.gravelyn.com Nick

    No problem. Thanks for the awesome sample. This effect is so going into my code. :)

  • http://amapplease.blogspot.com Pete

    “This effect is so going into my code.”

    Ditto.

  • http://machaira.spaces.live.com Jim Perry

    The energy bolt effect will come in handy in a game I’ve got in the works. :)

  • Pingback: UH COSC Interactive Game Development » XNA Lightning Sample

  • Deana

    Oh my god, i have nearly cum in my pants playing with this!!! It’s amazing!

  • JCW

    Hi Catalin

    This is an amazing sample. May I ask for your advice?

    I am creating a RPG in 3d. I want to have a lightning spell that looks like this. However, since this lightning is drawn with the spritebatch and in the 2d background, my terrain model covers up most of the lightning, so you cannot see the lightning. How can I create a lightning spell that moves from one player to another in 3d?

  • http://www.catalinzima.com Catalin Zima

    The actual lightning branches are all 3D vertices.
    To put them in a 3D scene, you would have to modify some code, and instead of rendering the lightning on a transparent render taget (liek I do), render it directly into your scene.

  • JCW

    Sorry, I am not very good with graphics. Can you upload a sample if it is not too hard for you? Thank you!

  • JCW

    Hi again,

    If I want to render the lightning effect in a 3d world, should I change texture coordinates in the lightning vertex class to a vector3, and then change the lightningpoint.texturecoordinate in the lightning bolt class to the point in 3d space?

  • http://www.catalinzima.com Catalin Zima

    No. The texture coordinates remain as they are. Each branch of the lighting should remains a billboard.

    You basically need to set to 3D the Positions of the points. You also need to Modify the GetJittered function to add a random Vector3 vector instead of a random Vector2 vector.

  • http://www.catalinzima.com Catalin Zima

    I would make the modifications for 3D, but I don’t really have much free time for this.

  • JCW

    Sorry Catalin, I hate to keep asking you questions. I will gladly send you the final modifications if I can successfully alter this.

    The lightning vertex positions and lightningPoints already have vector 3s, so when you say set to 3d the positions of the points, are you referring to this code?

    using (VertexDeclaration vdecl = new VertexDeclaration(device, LightningVertex.VertexElements))
    {
    device.VertexDeclaration = vdecl;
    device.RenderState.CullMode = CullMode.None;
    lightningDrawEffect.Begin();
    lightningDrawEffect.CurrentTechnique.Passes[0].Begin();
    device.DrawUserIndexedPrimitives(PrimitiveType.TriangleList, lightningPoints, 0, lightningPoints.Length, indices, 0, indices.Length / 3);
    lightningDrawEffect.CurrentTechnique.Passes[0].End();
    lightningDrawEffect.End();
    }

    Sorry, this is the first time I am doing something advanced with graphics. I have already learned a lot from your sample!

  • http://www.catalinzima.com Catalin Zima

    No, that code is fine as it is.

    I mean when you set the StartPoint and EndPoint.
    In truth, most code already works with Vector3 wherever possible. So as I said above, I believe chaging the GetJitter function to add a random Vector3 should do the trick.

  • JCW

    Wow it was that simple?! I changed getJitter to use a random vector3 and created a new property called JitterRightDeviation and a new method called GetRight to match the GetLeft method that you have. The lightning renders with a point in 3d for its source, but the destination still seems to be a point somewhere in 2D. Here is an image of my program. http://img300.imageshack.us/my.php?image=lightningkq9.jpg

    The lightning should go from the person on the left to the person on the right, but it is going to the background for some reason? Also, you can only see the lightning if the player is jumping and above the terrain.

    This is an amazing sample, beautifully made!

  • http://www.catalinzima.com Catalin Zima

    That’s probably related to the depth buffer.

  • http://www.europeinruins.com LuciferNZ

    Hiya, Ive implemented a 3d version of this, but split it into its own Draw() function so that I can render it with a depth buffer.
    This bit works, it creates a 3d Jitter.

    The only problem Im finding now, is that I cannot for the life of me, get the X/Y/Z coords to face the camera correctly.

    So, from some angles, it looks fine, and from others – really really bad.

    Is there something Im missing?

  • http://haxpor.org haxpor

    Thanks alot.

    I will try to integrate this stuff into my deferred shading, it probably works well in alpha drawing.

  • http://haxpor.org haxpor

    I have finished integrating this stuff into my deferred shading.
    I use it for my rainy scene with the following setup.

    LightningDescriptor ld = new LightningDescriptor();
    ld.AnimationFramerate = 12f;
    ld.ExteriorColor = Color.WhiteSmoke;
    ld.GlowIntensity = 3f;

    Also when the time to draw the lightning is come, I only randomize once for the source point, but then every frame for destination point. (For this case I have one flag indicates that the lightning is started to draw yet, so the only one time for randomization of source point can be accomplished.)

    One last note, I duration for the lightning in the rainy scene should not be more than 1 seconds, for my setup, I used 1, 0.75f, 0.5f seconds for many different pattern for my lightning.

    Thanks for this great stuff.

  • http://www.lucidvisiongames.com Todd

    I am attempting to use your effect in 3D. All I had to do was comment out the render target code and it works perfectly fine on PC. However, when I run it on the 360 it looks horrible, the lighting bolts have black squares and black sections. Here are the changes I made to the code:

    public void GenerateTexture(GameTime gameTime, Matrix world, Matrix view, Matrix projection)
    {
    GraphicsDevice device = game.GraphicsDevice;

    //device.SetRenderTarget(0, lightningRT);
    //device.Clear(ClearOptions.Target,Color.TransparentBlack,1.0f,0);

    lightningDrawEffect.Parameters[“World”].SetValue(world);
    lightningDrawEffect.Parameters[“View”].SetValue(view);
    lightningDrawEffect.Parameters[“Projection”].SetValue(projection);
    lightningDrawEffect.Parameters[“StartColor”].SetValue(properties.InteriorColor.ToVector3());
    lightningDrawEffect.Parameters[“EndColor”].SetValue(properties.ExteriorColor.ToVector3());

    device.RenderState.AlphaBlendEnable = true;
    device.RenderState.BlendFunction = BlendFunction.Max;

    using (VertexDeclaration vdecl = new VertexDeclaration(device, LightningVertex.VertexElements))
    {
    device.VertexDeclaration = vdecl;
    device.RenderState.CullMode = CullMode.None;
    lightningDrawEffect.Begin();
    lightningDrawEffect.CurrentTechnique.Passes[0].Begin();
    device.DrawUserIndexedPrimitives(PrimitiveType.TriangleList, lightningPoints, 0, lightningPoints.Length, indices, 0, indices.Length / 3);
    lightningDrawEffect.CurrentTechnique.Passes[0].End();
    lightningDrawEffect.End();
    }

    //device.SetRenderTarget(0, null);
    //if(properties.IsGlowEnabled)
    // postProcessGlow.ApplyEffect(lightningRT, lightningRT, properties.GlowIntensity);
    }

    protected override void Draw(GameTime gameTime)
    {
    GraphicsDevice.Clear(Color.Black);

    //draw it in 2D
    Matrix viewMatrix = Matrix.CreateLookAt(new Vector3(0, 0, 10), new Vector3(0, 0, 0), new Vector3(0, 1, 0));
    Matrix projectionMatrix = Matrix.CreateOrthographic(GraphicsDevice.Viewport.Width / 20, GraphicsDevice.Viewport.Height / 20, 0.01f, 50);
    Matrix worldMatrix = Matrix.Identity;

    //generate the lightning rendering
    lightnings[currentItem].GenerateTexture(gameTime, worldMatrix, viewMatrix, projectionMatrix);

    Rectangle rect = new Rectangle(0, 0, GraphicsDevice.Viewport.Width, GraphicsDevice.Viewport.Height);

    //GraphicsDevice.Clear(Color.Black);
    //spriteBatch.Begin(SpriteBlendMode.Additive);
    //if (showBackground)
    // spriteBatch.Draw(background,rect,Color.White);
    ////draw lightning texture over the scene
    //spriteBatch.Draw(lightnings[currentItem].LightningTexture, rect, Color.White);
    //spriteBatch.End();

    base.Draw(gameTime);
    }

  • Marco

    Fantastic sample!
    I’m trying to use lightning effect in a 2D game but I have some trouble to set source and destination point because I cannot understand how to “convert” from screen coordinates (the game use 1280×800 screen size)to lightning source/destination coordinates;
    Can you help me?

    Thanks,
    Marco

  • http://www.2point0studios.com Daniel Armstrong

    Hiya, Ive implemented a 3d version of this. It still renders along a 2d plane but is rendered in 3d. I also created a 3d jitter function but that didn’t seem to change anything.

    The only problem Im finding now, is that I cannot for the life of me, get the X/Y/Z coords to face the camera correctly.

    So, from some angles, it looks fine, and from others – really really bad.

    Is there something Im missing?
    Please Help.

  • http://none PreZrayGUN

    I’ve downloaded and run the sample.
    It doesn’t do anything for me.

    I can run it with no errors, make the background appear and disappear and exit.

    How do I make the lightning appear?

    -=PreZ=-

  • zanlok

    This looks fantastic, and very true to the original sample. My use would be 2D, to pre-render sprites of (glowy/neon) laserbeams. I’d absolutely love for a version of this to be updated and run-able in the new 4.0 version of the XNA Game Studio framework.

    I’m trying out a re-instrumentation of the code, but may not be successful. If anyone already wanted to do this, then I’d love to hear about it.

  • http://Website Jordan

    I have tried to convert this to XNA 4.0 with no success I am to new to XNA, even though I have spent hours fixing all the errors more keep coming, if anyone has or can succesfully convert this to 4.0 please email it to me at djdduty@gmail.com I will give many many thanks

  • http://Website Daniel

    Any 4.0 version of this?

    Converting it has so far failed for me…
    So many things changed…

  • http://www.hatchingdisaster.com Nick

    I upgraded this to 4.0 because I needed the effect for a project. Please note some parameters and colours may be different. Works fine when I compiled and ran using VS2010 Express.

    http://www.hatchingdisaster.com/LightningSampleXNA4.zip

  • http://Website Ed

    Cool effects. One question… can we use these classes in our commercial projects?

    What are the license terms?

    (I will put your names in the credits, of course).

    Thank you.