代码之家  ›  专栏  ›  技术社区  ›  PiotrK

如何在SpriteBatch Draw XNA(2D)中倍增两个精灵

  •  4
  • PiotrK  · 技术社区  · 16 年前

    我正在XNA3.1中为动作rpg编写简单的十六进制引擎。我想点燃英雄和火把附近的地面,就像他们在暗黑破坏神II中被点燃一样。我认为最好的方法是计算视野,隐藏玩家看不到的任何瓷砖及其内容,并在任何光源上绘制特殊的“光”纹理:黑色纹理,中间有白色模糊的圆圈。

    我想将这个纹理与背景相乘(就像在混合模式中:相乘),但不幸的是,我在SpriteBatch中看不到这样做的选项。有人能给我指出正确的方向吗?

    3 回复  |  直到 16 年前
        1
  •  7
  •   Tom Gillen    16 年前

    如果要将灯光纹理与场景相乘,则 变暗 区域,而不是照亮它。

    可以尝试使用加法混合进行渲染;这看起来不太正确,但很容易,可能是可以接受的。你必须用相当低的alpha值来绘制光线,这样光线纹理就不会对图像的这一部分过度饱和。

    另一种更复杂的照明方式是将所有灯光纹理(场景中的所有灯光)添加到第二个渲染目标上,然后将该纹理与场景相乘。这将提供更真实的照明,但性能开销更大,更复杂。

    初始化:

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

    // 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();
    
        2
  •  2
  •   Martin    16 年前

    据我所知,如果不使用您自己的自定义着色器,就无法做到这一点。

    用于此的自定义着色器的工作原理如下:

    1. 将场景渲染为纹理
    2. 将灯光渲染到其他纹理
    3. 作为对空白四边形的后处理,对两个纹理进行采样,结果是场景纹理*灯光纹理。

    this excellent sample from Catalin Zima

        3
  •  1
  •   Peter Lillevold Rene    16 年前

    可能使用与中相同的技术 the BloomEffect component 可能是个主意。

    这里也可以使用同样的方法。这将更简单,因为您不必根据背景计算bloom图像,只需根据角色的位置即可。

    您甚至可以进一步重用它,为其他光源提供高亮显示,例如火炬、魔术效果等等。