【Unity面试题】URP中如何实现截屏?如何只截取主相机画面?

一、截取整个屏幕(含 UI)

原理:
在 URP 中,相机不能依赖 Camera.Render() 强制渲染完整内容,因此截取单个相机的正确方式,是让该相机将其输出写入一个自定义 RenderTexture,然后再从这个 RenderTexture 中通过 ReadPixels() 读取像素。由于此时 RenderTexture.active 被设置为该 RT,ReadPixels() 读取的就是该相机的独立渲染结果,不会包含其他相机,也不会包含 Overlay 模式的 UI,因此非常适合“只截主相机”、“不带 UI 的游戏画面”,或“离屏渲染”。

步骤:

  1. 创建一个 RenderTexture(匹配你需要的分辨率)。
  2. 将主相机的 targetTexture 设置为该 RenderTexture。
  3. 在本帧末尾(WaitForEndOfFrame)调用 cam.Render() 或依赖 URP 自动渲染。
  4. 设置 RenderTexture.active = rt
  5. 调用 ReadPixels() 将 RenderTexture 读入 Texture2D。
  6. 调用 Apply() 然后恢复:cam.targetTexture = null; RenderTexture.active = null;
    7.(可选)保存为图片。

实现:

public IEnumerator CaptureFullScreen()
{
    yield return new WaitForEndOfFrame(); // 等待 URP 整帧绘制完成

    int width = Screen.width;
    int height = Screen.height;

    Texture2D tex = new Texture2D(width, height, TextureFormat.RGB24, false);

    tex.ReadPixels(new Rect(0, 0, width, height), 0, 0); // 从 FrameBuffer 读
    tex.Apply();

    // 保存
    string path = Application.dataPath + "/../Screenshot.png";
    System.IO.File.WriteAllBytes(path, tex.EncodeToPNG());

    Debug.Log("Full screen screenshot saved: " + path);
}

二、截主相机画面(单独相机 RenderTexture 截图)

原理:

在 URP 中,所有相机的颜色输出、后处理效果以及 UGUI 的最终渲染结果,都会被写入到屏幕的 Back Buffer(FrameBuffer)中。在整帧渲染结束后,只要不修改 RenderTexture.active,Unity 默认将 FrameBuffer 当作当前的 Active RenderTarget。此时调用 Texture2D.ReadPixels(),读取的就是这一帧屏幕最终成品的像素数据,因此可以完整保留所有 UI、所有 Camera 的叠加画面。为了确保 FrameBuffer 内容已渲染完毕,必须在 WaitForEndOfFrame() 之后执行。

步骤:

  1. yield return new WaitForEndOfFrame() 等待 URP 完成整帧渲染。
  2. 不设置任何 RenderTexture(保持 RenderTexture.active = null)。
  3. 创建一个 Texture2D(RGB24 或 RGBA32)。
  4. 调用 ReadPixels(new Rect(0,0,w,h), 0,0) 直接从 FrameBuffer 读取像素。
  5. 调用 Apply() 生成最终纹理。
    6.(可选)编码为 PNG/JPG 保存。

实现:

public IEnumerator CaptureMainCamera(Camera cam, int width, int height)
{
    yield return new WaitForEndOfFrame();

    RenderTexture rt = new RenderTexture(width, height, 24);
    cam.targetTexture = rt;

    // 在 URP 中,等待到这一帧结束,Camera.Render() 不强制必须
    cam.Render();

    RenderTexture.active = rt;

    Texture2D tex = new Texture2D(width, height, TextureFormat.RGB24, false);
    tex.ReadPixels(new Rect(0, 0, width, height), 0, 0);
    tex.Apply();

    cam.targetTexture = null;
    RenderTexture.active = null;

    // 保存到文件
    string path = Application.dataPath + "/../MainCamera.png";
    System.IO.File.WriteAllBytes(path, tex.EncodeToPNG());

    Debug.Log("Main camera screenshot saved: " + path);
}


如果要性能更好(避免 ReadPixels 卡顿)

Unity2021 支持 AsyncGPUReadback,不会卡主线程

AsyncGPUReadback.Request(rt, 0, TextureFormat.RGBA32, OnReadbackComplete);

void OnReadbackComplete(AsyncGPUReadbackRequest req)
{
    if (req.hasError)
    {
        Debug.LogError("Readback Error!");
        return;
    }

    var tex = new Texture2D(width, height, TextureFormat.RGBA32, false);
    tex.LoadRawTextureData(req.GetData<byte>());
    tex.Apply();
}

### 启用 Progressive Lightmapper 的方法 在 Unity URP 中启用 **Progressive Lightmapper** 是实现高质量光照烘焙的关键步骤。该功能在 Unity 2019.4 版本中正式替代了已弃用的 Enlighten 烘焙系统,提供了更高质量的光照计算能力[^1]。 确保项目中已启用 URP,这一步是前提条件之一。URP 是一种轻量级、高性能的可编程渲染管线,特别适合移动平台和性能敏感的项目[^2]。启用 URP 后,可以通过以下步骤配置 Progressive Lightmapper: 在 Unity 编辑器中打开 **Lighting Settings** 窗口(Window > Rendering > Lighting Settings)。在该窗口中,找到 **Lightmapper** 选项,并将其设置为 **Progressive CPU** 或 **Progressive GPU (Preview)**。Progressive GPU 模式可以显著加快烘焙速度,但需确保硬件支持该功能。 为了获得更精确的光照效果,建议调整以下参数: - **Lightmap Resolution**:控制光照贴图的分辨率,数值越高,光照细节越清晰,但会增加烘焙时间和内存占用。 - **Direct Samples / Indirect Samples**:影响光照计算的采样次数,数值越高,光照越平滑,但烘焙时间也会增加。 - **Final Gather**:开启此选项可提升光照贴图的柔和度,尤其在复杂场景中效果更佳。 确保参与烘焙的静态物体已正确标记为 **Static**,并且模型导入设置中启用了 **Generate Lightmap UVs**。这是确保光照贴图能正确映射到模型表面的重要步骤[^2]。 此外,场景中的光源应根据需求设置为 **Baked** 或 **Mixed** 模式,以决定是否参与光照贴图烘焙。对于需要动态变化的光源,建议使用 **Light Probes** 和 **Reflection Probes** 来增强动态物体的光照和反射效果。 ### 示例:通过脚本设置光照贴图分辨率 ```csharp // 在 Lighting 窗口中设置光照贴图分辨率 LightmapSettings.lightmapsResolution = 1024; ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值