简体   繁体   English

如何在SpriteBatch Draw XNA(2D)中相乘两个精灵

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

I am writing simple hex engine for action-rpg in XNA 3.1. 我正在为XNA 3.1中的动作RPG编写简单的十六进制引擎。 I want to light ground near hero and torches just as they were lighted in Diablo II. 我想在暗黑破坏神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. 我想将这个纹理与背景相乘(如混合模式:乘法),但是 - 不幸的是 - 我没有看到在SpriteBatch中这样做的选项。 Could someone point me in right direction? 有人能指出我正确的方向吗?

Or perhaps there is other - better - way to achive lighting model as in Diablo II? 或者也许还有其他 - 更好的方式来实现暗黑破坏神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. 您将不得不使用相当低的alpha绘制光线,以获得轻盈的纹理,而不仅仅是过度饱和图像的那部分。

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 如果你想要阴影,我建议你遵循Catalin Zima的优秀样本

Perhaps using the same technique as in the BloomEffect component could be an idea. 也许使用与BloomEffect组件中相同的技术可能是一个想法。

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. 您甚至可以进一步重复使用它来为其他光源提供高亮显示,例如火把,魔法效果等等。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM