English 中文(简体)
How to multiply two sprites in SpriteBatch Draw XNA (2D)
原标题:
  • 时间:2009-12-30 21:57:57
  •  标签:
  • xna
  • 2d

I am writing simple hex engine for action-rpg in XNA 3.1. I want to light ground near hero and torches just as they were lighted in Diablo II. I though the best way to do so was to calculate field-of-view, hide any tiles and their s content that player can t see and draw special "Light" texture on top of any light source: Texture that is black with white, blurred circle in it s center.

I wanted to multiply this texture with background (as in blending mode: multiply), but - unfortunately - I do not see option for doing that in SpriteBatch. Could someone point me in right direction?

Or perhaps there is other - better - way to achive lighting model as in Diablo II?

最佳回答

If you were to multiply your light texture with the scene, you will darken the area, not brighten it.

You could try rendering with additive blending; this won t quite look right, but is easy and may be acceptable. You will have to draw your light with a fairly low alpha for the light texture to not just over saturate that part of the image.

Another, more complicated, way of doing lighting is to draw all of your light textures (for all the lights in the scene) additively onto a second render target, and then multiply this texture with your scene. This should give much more realistic lighting, but has a larger performance overhead and is more complex.

Initialisation:

RenderTarget2D lightBuffer = new RenderTarget2D(graphicsDevice, screenWidth, screenHeight, 1, SurfaceFormat.Color);
Color ambientLight = new Color(0.3f, 0.3f, 0.3f, 1.0f);

Draw:

// set the render target and clear it to the ambient lighting
graphicsDevice.SetRenderTarget(0, lightBuffer);
graphicsDevice.Clear(ambientLight)

// additively draw all of the lights onto this texture. The lights can be coloured etc.
spriteBatch.Begin(SpriteBlendMode.Additive);
foreach (light in lights)
    spriteBatch.Draw(lightFadeOffTexture, light.Area, light.Color);
spriteBatch.End();

// change render target back to the back buffer, so we are back to drawing onto the screen
graphicsDevice.SetRenderTarget(0, null);

// draw the old, non-lit, scene
DrawScene();

// multiply the light buffer texture with the scene
spriteBatch.Begin(SpriteBlendMode.Additive, SpriteSortMode.Immediate, SaveStateMode.None);
graphicsDevice.RenderState.SourceBlend = Blend.Zero;
graphicsDevice.RenderState.DestinationBlend = Blend.SourceColor;
spriteBatch.Draw(lightBuffer.GetTexture(), new Rectangle(0, 0, screenWidth, screenHeight), Color.White);
spriteBatch.End();
问题回答

As far as I know there is no way to do this without using your own custom shaders.

A custom shader for this would work like so:

  1. Render your scene to a texture
  2. Render your lights to another texture
  3. As a post process on a blank quad, sample the two textures and the result is Scene Texture * Light Texture.

This will output a lit scene, but it won t do any shadows. If you want shadows I d suggest following this excellent sample from Catalin Zima

Perhaps using the same technique as in the BloomEffect component could be an idea.

Basically what the effect does is grabbing the rendered scene, calculates a bloom image from the brightest areas in the scene, the blurs and combines the two. The result is highlighting areas depending on color.

The same approach could be used here. It will be simpler since you won t have to calculate the bloom image based on the background, only based on the position of the character.

You could even reuse this further to provide highlighting for other light sources as well, such as torches, magic effects and whatnot.





相关问题
c# wpf 2d graphics - Looking for tutorial / examples [closed]

Could you please point me to a good C# tutorial for drawing 2d graphics like Ellipse and Rectangle (that inherit from Shape) on a Canvas using WPF ? I m also interested later to click on shapes and ...

How to multiply two sprites in SpriteBatch Draw XNA (2D)

I am writing simple hex engine for action-rpg in XNA 3.1. I want to light ground near hero and torches just as they were lighted in Diablo II. I though the best way to do so was to calculate field-of-...

2D Ball Collisions with Corners

I m trying to write a 2D simulation of a ball that bounces off of fixed vertical and horizontal walls. Simulating collisions with the faces of the walls was pretty simple--just negate the X-velocity ...

2D Mathematics Geographical Directions

I am trying to check the location of a point(px, py) on 2D graph in relation to a line segment (lx1, ly1) (lx2, ly2), using logic of North South East West directions. The logic I have implemented is ...

Perpendicular on a line from a given point

How can I draw a perpendicular on a line segment from a given point? My line segment is defined as (x1, y1), (x2, y2), If I draw a perpendicular from a point (x3,y3) and it meets to line on point (x4,...

How to select a line

So I m trying to figure out how to implement a method of selecting lines or edges in a drawing area but my math is a bit lacking. This is what I got so far: A collection of lines, each line has two ...

How do I generate a contour graph?

How do I generate a contour graph like this: contour http://www.fz-juelich.de/vislab/software/gsharp/Gsharp/userguide/interpolate/ex6.gif It s easy enough if the points are on a regular grid, but ...

Mapping points from Euclician 2-space onto a Poincare disc

For some reason it seems that everyone writing webpages about Poincare discs is only concerned with how to represent lines and measure distances. I d like to morph a collection of 2D points (as ...

热门标签