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

如何在SpriteBatch Draw XNA(2D)中倍增两个精灵,xna,2d,Xna,2d,我正在XNA3.1中为动作rpg编写简单的十六进制引擎。我想点燃英雄和火把附近的地面,就像他们在暗黑破坏神II中被点燃一样。我认为最好的方法是计算视野,隐藏玩家看不到的任何瓷砖及其内容,并在任何光源上绘制特殊的“光”纹理:黑色纹理,中间有白色模糊的圆圈 我想将这个纹理与背景相乘(就像在混合模式中:相乘),但不幸的是,我在SpriteBatch中看不到这样做的选项。有人能给我指出正确的方向吗 或者,也许还有其他更好的方法来实现暗黑破坏神II中的照明模型?据我所知,如果不使用自己的自定义着色器,就无

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

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


或者,也许还有其他更好的方法来实现暗黑破坏神II中的照明模型?

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

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

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

  • 这将输出一个照亮的场景,但不会产生任何阴影。如果您想要阴影,我建议您使用与中相同的技术

    基本上,效果就是抓取渲染场景,从场景中最亮的区域计算一个bloom图像,模糊并将两者结合起来。结果是根据颜色高亮显示区域

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


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

    如果要将灯光纹理与场景相乘,则会使该区域变暗,而不是变亮

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

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

    初始化:

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


    这与我的建议类似,但可能更好,因为您可以从bloom示例中获取示例代码
    // 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();