XNA 屏幕截图显示预绽放,而不是最终渲染

2024-03-28

我有一个使用 Reach 图形设置在 C# XNA 4.0 中编码的 Windows 平台游戏。我的项目基于 GameStateManagement 示例,但后来我向其中添加了 Bloom 和 spriteSheet/spriteBatch 功能。

我希望保存最终屏幕输出的屏幕截图。但是,当我保存屏幕截图时,它仅显示应用 Bloom 之前和显示 HUD 文本之前的渲染(我在 Bloom 之后绘制)。在这两个过程之后,我将屏幕截图保存在 Draw 方法的末尾。

我尝试过各种各样的事情。安德鲁的回答在这里在 XNA 中截取屏幕截图 https://stackoverflow.com/questions/1775196/take-screen-shot-in-xna很有帮助,并且确实保存了图像;但是,它并没有保存最终渲染。

我有一种感觉,这与绽放过程或精灵批次有关。

这是我的代码:

    example {
    public override void Draw(GameTime gameTime)
    {
        ScreenManager.GraphicsDevice.SetRenderTarget(sceneRenderTarget);
        // Clear the screen to black
        ScreenManager.GraphicsDevice.Clear(ClearOptions.Target,
                                           Color.Black, 0, 0);
        SpriteBatch spriteBatch = ScreenManager.SpriteBatch;
        spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend);

    // then i draw all my game stuff

        spriteBatch.End();

        #region Post-Processing & Bloom
        ScreenManager.GraphicsDevice.SamplerStates[1] = SamplerState.LinearClamp;

        // Pass 1: draw the scene into rendertarget 1, using a
        // shader that extracts only the brightest parts of the image.
        bloomExtractEffect.Parameters["BloomThreshold"].SetValue(
            Settings.BloomThreshold);

        DrawFullscreenQuad(sceneRenderTarget, renderTarget1,
                           bloomExtractEffect,
                           IntermediateBuffer.PreBloom);

        // Pass 2: draw from rendertarget 1 into rendertarget 2,
        // using a shader to apply a horizontal gaussian blur filter.
        SetBlurEffectParameters(1.0f / (float)renderTarget1.Width, 0);

        DrawFullscreenQuad(renderTarget1, renderTarget2,
                           gaussianBlurEffect,
                           IntermediateBuffer.BlurredHorizontally);

        // Pass 3: draw from rendertarget 2 back into rendertarget 1,
        // using a shader to apply a vertical gaussian blur filter.
        SetBlurEffectParameters(0, 1.0f / (float)renderTarget1.Height);

        DrawFullscreenQuad(renderTarget2, renderTarget1,
                           gaussianBlurEffect,
                           IntermediateBuffer.BlurredBothWays);

        // Pass 4: draw both rendertarget 1 and the original scene
        // image back into the main backbuffer, using a shader that
        // combines them to produce the final bloomed result.
        ScreenManager.GraphicsDevice.SetRenderTarget(null);

        EffectParameterCollection parameters = bloomCombineEffect.Parameters;

        parameters["BloomIntensity"].SetValue(Settings.BloomIntensity);
        parameters["BaseIntensity"].SetValue(Settings.BaseIntensity);
        parameters["BloomSaturation"].SetValue(Settings.BloomSaturation);
        parameters["BaseSaturation"].SetValue(Settings.BaseSaturation);

        ScreenManager.GraphicsDevice.Textures[1] = sceneRenderTarget;

        Viewport viewport = ScreenManager.GraphicsDevice.Viewport;

        DrawFullscreenQuad(renderTarget1,
                           viewport.Width, viewport.Height,
                           bloomCombineEffect,
                           IntermediateBuffer.FinalResult);

        #endregion

        spriteBatch.Begin();
        // Draw HUD
        spriteBatch.End();


        if (screenShotTake)
        {
            using (FileStream fs = File.Open(@"screenshot" + (screenshotNumber) + @".png", FileMode.OpenOrCreate))
            {
                // Right here I try to save out the screen shot Texture2D
                sceneRenderTarget.SaveAsPng(fs, (int)viewportSize.X, (int)viewportSize.Y); // save render target to disk
            }
        }
    }




    #region PostProcess & Bloom
    void DrawFullscreenQuad(Texture2D texture, RenderTarget2D renderTarget,
                            Effect effect, IntermediateBuffer currentBuffer)
    {
        ScreenManager.GraphicsDevice.SetRenderTarget(renderTarget);

        DrawFullscreenQuad(texture,
                           renderTarget.Width, renderTarget.Height,
                           effect, currentBuffer);


    }

    void DrawFullscreenQuad(Texture2D texture, int width, int height,
                            Effect effect, IntermediateBuffer currentBuffer)
    {
        if (showBuffer < currentBuffer)
        {
            effect = null;
        }

        spriteBatch.Begin(0, BlendState.Opaque, null, null, null, effect);
        spriteBatch.Draw(texture, new Rectangle(0, 0, width, height), Color.White);
        spriteBatch.End();
    }

}


问题就在这里:

ScreenManager.GraphicsDevice.SetRenderTarget(null);

由于这条线,您将效果绘制到后台缓冲区,但您要保存的渲染目标保持不变。您会看到效果的结果,因为它是直接绘制的,但您保存的内容并不是绘制到后台缓冲区的内容。要解决此问题,请将效果绘制到另一个 RenderTarget,然后将其作为单个纹理绘制到后台缓冲区。显然,这是另一个要处理的绘制调用,但成本最小。通过这样做,您可以从新的 RenderTarget 中获取纹理并按照您喜欢的方式保存它。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

XNA 屏幕截图显示预绽放,而不是最终渲染 的相关文章

随机推荐

  • 获取所有Android版本中来电的电话号码

    我正在尝试获取来电的来电号码 我搜索并找到了这个在 Android 中检索来电的电话号码 https stackoverflow com questions 1853220 retrieve incoming calls phone num
  • 如何包装 OAuth2 异常?

    我们有一个 REST API 使用Spring OAuth2 用户通过身份验证后 所有 JSON 响应均采用以下格式 code 12345 data 但是身份验证失败的 JSON 响应与上述格式不相符 因为这是由 Spring 处理的 例如
  • get_class() 期望参数 1 为对象,给定为 null

    当我尝试在新的本地计算机上部署 Symfony 2 8 项目时 我在代码的多个位置遇到此错误 Warning get class expects parameter 1 to be object null given 在stackoverf
  • 如何清理(用随机字节覆盖)std::string 内部缓冲区?

    考虑一个场景 其中std string用于存储a secret 一旦它被消耗并且不再需要 最好清理它 即覆盖包含它的内存 从而隐藏它secret std string提供一个函数const char data 返回指向 C 11 起 连续内
  • 根据匹配的列标题名称开头组合 R 中的列

    我有一个看起来有点像下面的数据框 A1U sweet 实际上是真实数据帧中的第 19 列 C1U sweet 是真实数据帧中的第 39 列 有 20 个以 A 开头的列和 20 个以 C 开头的列 A1U sweet A2F dip A3U
  • 在 Chapel 中使用矩阵创建域

    我有一个域名D 我想用它来索引几个矩阵A 某种形式的东西 var dom domain 1 0 5 var mats dom
  • 如何获取 PromptDialog.Choice 功能并仍然允许 Bot Framework 中的其他用户响应?

    Bot Framework 中的 PromptDialog Choice 提供了许多运行良好的内置功能 但是 我希望能够拦截 覆盖匹配过程 获得 PromptDialog Choice 功能并且还能够接受某些可能不匹配的字符串的最佳方法是什
  • 卡西尼号源代码下载链接?

    有谁知道哪里可以下载卡西尼号的源代码吗 我尝试了链接http www asp net Projects Cassini Download http www asp net Projects Cassini Download但该页面现在不存在
  • 如何从“struct linux_binprm”获取argv

    我想使用 bprm check security lsm 挂钩来检查是否允许运行具有特定参数的进程 在文档中 我看到 argv 应该在 bprm 类型为 struct linux binprm 中可用 但我没有找到任何从结构中提取 argv
  • 需要VC6平台SDK

    有谁知道我可以在哪里下载最后一个与 VC6 一起使用的 Platform SDK 我通过谷歌搜索找到的链接似乎都已失效 我设法在这里找到它 官方或非官方 http docs moodle org dev FebruaryPlatformSD
  • Gradle 日志在哪里?

    Android Studio 中应用程序的 Gradle 构建会生成以下错误 Error Execution failed for task app compileDebugJavaWithJavac gt java lang Runtim
  • 计算所有结构不同的二叉树的数量的时间复杂度是多少?

    使用此处介绍的方法 http cslibrary stanford edu 110 BinaryTrees html java http cslibrary stanford edu 110 BinaryTrees html java 12
  • 变量列表中的逗号是序列点吗?

    在以下类型的代码中 每个变量构造之间是否存在序列点 或者结果未定义 int a 0 int b a c a 我无法在标准中找到对此处序列点的具体引用 这是否意味着它未定义 或者只是我的搜索失败了 表达式的完成是一个序列点 但是上面的初始化也
  • 在 R 中为 pentium 4 HT 机器使用多核

    我在办公室使用Pentium 4 HT机器来运行R 一些代码需要plyr包 我通常需要等待6 7分钟才能完成脚本运行 而我看到我的处理器只使用了一半 我听说在 R 中使用多核包可以更好地利用多核处理器 我的情况适合吗 Thanks 有很多软
  • PyInstaller 2.1导入自定义包

    我有一个脚本正在尝试使用 Python 2 7 使用 PyInstaller 2 1 进行编译 该脚本使用我编写的名为 auto common 的自定义包 在脚本中 我使用以下命令导入它 sys path append path to pa
  • 如何在 Jupyter 中插入文字选项卡而不是自动完成?

    缩进整行很容易 Just highlight the whole line and press Tab Go to the start of the line and press Tab Click anywhere in the line
  • 如何获取枚举数

    如何获取枚举数 我有一个枚举 typedef enum DEL TIME VALUE 1 DEL TIMESEC VALUE 100 DEL TIMEMIN VALUE 200 DEL TIMEHOUR VALUE 300 DEL DAY
  • 用正则表达式获取最终的特殊字符

    我想要一个正则表达式 将字符串末尾的一些特殊字符分组 特殊字符是 和空格 例如 如果我有字符串 test 我想在组中获取字符串 我创建了以下正则表达式 问题是它给了我以下字符串 为什么要提取最后的括号 Put the 字符类中第一个或最后一
  • 循环选择某列并单独保存

    我的数据框是 c1 c2 c3 c100 0 2 0 4 0 9 0 0 2 0 3 0 1 0 1 0 6 1 0 3 我想选择c1 c2和c3 c1 c2和c4 类似的c1 c2和c100 每 3 个选定的列应保存在单独的文件中 我该怎
  • XNA 屏幕截图显示预绽放,而不是最终渲染

    我有一个使用 Reach 图形设置在 C XNA 4 0 中编码的 Windows 平台游戏 我的项目基于 GameStateManagement 示例 但后来我向其中添加了 Bloom 和 spriteSheet spriteBatch