Unity Shader - 踩坑 - BRP 管线中的 depth texture 的精度问题(暂无解决方案,推荐换 URP)


环境

Unity: 2018.2.11f1
Pipeline: BRP
Platform : Android
Graphics API : OpenGL ES 3/+
Color Space : Linear


问题

部分移动设备的 GPU 精度比较低,会导致精度表现不佳的异常显示
(本来想用 RenderDoc, Snapdragon Profiler 来查看真机的 FB 的格式,但是这两个工具都越来越不给力了,市场上能用的真机抓帧工具越来越少,基本上现在能用的就只用 RenderDoc抓PC,Intel GPA抓PC,Snapdragon Profiler 只能抓高通机型的部分应用:必须开启 debuggable, read/write permission 要开启才能抓,但是 Snapdragon Profiler很多BUG,经常崩溃、闪退,或是无法显示 Pixel History 数据,现在这些大厂,或是主流工具都这么不给力了吗?-_-!!!)

比如:

  • 软粒子与 opaque 内容 fade 过度异常
  • 水体与 opaque 内容的 深度 fade 过度异常

经过一番测试,最终无法解决,还好未来新项目使用的是URP


测试 Shader 部分代码

// depth gradient control foam
float sceneZ = LinearEyeDepth(SAMPLE_DEPTH_TEXTURE_PROJ(_CameraDepthTexture, UNITY_PROJ_COORD(i.projPos)));
float fragZ = i.projPos.z;
// return sceneZ;
// return fragZ;
float detalZ = sceneZ-fragZ;
return saturate(detalZ); // 这里再:oppo, vivo 的低端手机中,会有精度丢失严重的问题,导致,PC上 和 低端设备上 效果差异很大

测试 C#

// jave.lin : 2022/06/29
// 测试 水体深度颜色过度异常的问题
// 后来定位到是:深度精度问题

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.UI;

public class Test_WaterReflectionError_Script : MonoBehaviour {
    
    

    public Text graphicsAPI_Text;
    // jave.lin : 之前我的: Unity - 画质设置 https://blog.csdn.net/linjf520/article/details/123546253
    // 文章中列出的打印
    public static string DumpSystemInfoByManualyPrint()
    {
    
    
        var list = new List<string>(
            new string[]{
    
    
                "SystemInfo:\n",
                "\tbatteryLevel:" + SystemInfo.batteryLevel,
                "\tbatteryStatus:" + SystemInfo.batteryStatus,
                "\toperatingSystem:" + SystemInfo.operatingSystem,
                "\toperatingSystemFamily:" + SystemInfo.operatingSystemFamily,
                "\tprocessorType:" + SystemInfo.processorType,
                "\tprocessorFrequency:" + SystemInfo.processorFrequency,
                "\tprocessorCount:" + SystemInfo.processorCount,
                "\tsystemMemorySize:" + SystemInfo.systemMemorySize,
                "\tdeviceUniqueIdentifier:" + SystemInfo.deviceUniqueIdentifier,
                "\tdeviceName:" + SystemInfo.deviceName,
                "\tdeviceModel:" + SystemInfo.deviceModel,
                "\tsupportsAccelerometer:" + SystemInfo.supportsAccelerometer,
                "\tsupportsGyroscope:" + SystemInfo.supportsGyroscope,
                "\tsupportsLocationService:" + SystemInfo.supportsLocationService,
                "\tsupportsVibration:" + SystemInfo.supportsVibration,
                "\tsupportsAudio:" + SystemInfo.supportsAudio,
                "\tdeviceType:" + SystemInfo.deviceType,
                "\tgraphicsMemorySize:" + SystemInfo.graphicsMemorySize,
                "\tgraphicsDeviceName:" + SystemInfo.graphicsDeviceName,
                "\tgraphicsDeviceVendor:" + SystemInfo.graphicsDeviceVendor,
                "\tgraphicsDeviceID:" + SystemInfo.graphicsDeviceID,
                "\tgraphicsDeviceVendorID:" + SystemInfo.graphicsDeviceVendorID,
                "\tgraphicsDeviceType:" + SystemInfo.graphicsDeviceType,
                "\tgraphicsUVStartsAtTop:" + SystemInfo.graphicsUVStartsAtTop,
                "\tgraphicsDeviceVersion:" + SystemInfo.graphicsDeviceVersion,
                "\tgraphicsShaderLevel:" + SystemInfo.graphicsShaderLevel,
                "\tgraphicsMultiThreaded:" + SystemInfo.graphicsMultiThreaded,
                "\tsupportsShadows:" + SystemInfo.supportsShadows,
                "\tsupportsRawShadowDepthSampling:" + SystemInfo.supportsRawShadowDepthSampling,
                "\tsupportsMotionVectors:" + SystemInfo.supportsMotionVectors,
                "\tsupports3DTextures:" + SystemInfo.supports3DTextures,
                "\tsupports2DArrayTextures:" + SystemInfo.supports2DArrayTextures,
                "\tsupports3DRenderTextures:" + SystemInfo.supports3DRenderTextures,
                "\tsupportsCubemapArrayTextures:" + SystemInfo.supportsCubemapArrayTextures,
                "\tcopyTextureSupport:" + SystemInfo.copyTextureSupport,
                "\tsupportsComputeShaders:" + SystemInfo.supportsComputeShaders,
                "\tsupportsInstancing:" + SystemInfo.supportsInstancing,
                "\tsupportsHardwareQuadTopology:" + SystemInfo.supportsHardwareQuadTopology,
                "\tsupports32bitsIndexBuffer:" + SystemInfo.supports32bitsIndexBuffer,
                "\tsupportsSparseTextures:" + SystemInfo.supportsSparseTextures,
                "\tsupportedRenderTargetCount:" + SystemInfo.supportedRenderTargetCount,
                "\tsupportsMultisampledTextures:" + SystemInfo.supportsMultisampledTextures,
                "\tsupportsMultisampleAutoResolve:" + SystemInfo.supportsMultisampleAutoResolve,
                "\tsupportsTextureWrapMirrorOnce:" + SystemInfo.supportsTextureWrapMirrorOnce,
                "\tusesReversedZBuffer:" + SystemInfo.usesReversedZBuffer,
                "\tnpotSupport:" + SystemInfo.npotSupport,
                "\tmaxTextureSize:" + SystemInfo.maxTextureSize,
                "\tmaxCubemapSize:" + SystemInfo.maxCubemapSize,
                "\tsupportsAsyncCompute:" + SystemInfo.supportsAsyncCompute,
                "\tsupportsAsyncGPUReadback:" + SystemInfo.supportsAsyncGPUReadback,
                "\tsupportsMipStreaming:" + SystemInfo.supportsMipStreaming,
            });
        return string.Join("\n", list.ToArray());
    }

    // jave.lin : 现在我们调试的话,只需要部分的即可
    public static string MyDump()
    {
    
    
        var list = new List<string>(
            new string[]{
    
    
                "SystemInfo:\n",
                "\toperatingSystem:" + SystemInfo.operatingSystem,
                "\toperatingSystemFamily:" + SystemInfo.operatingSystemFamily,
                "\tdeviceName:" + SystemInfo.deviceName,
                "\tdeviceType:" + SystemInfo.deviceType,
                "\tgraphicsMemorySize:" + SystemInfo.graphicsMemorySize,
                "\tgraphicsDeviceName:" + SystemInfo.graphicsDeviceName,
                "\tgraphicsDeviceVendor:" + SystemInfo.graphicsDeviceVendor,
                "\tgraphicsDeviceType:" + SystemInfo.graphicsDeviceType,
                "\tgraphicsDeviceVersion:" + SystemInfo.graphicsDeviceVersion,
                "\tgraphicsShaderLevel:" + SystemInfo.graphicsShaderLevel,
                "\tsupportsComputeShaders:" + SystemInfo.supportsComputeShaders,
                "\tsupportsInstancing:" + SystemInfo.supportsInstancing,
                "\tusesReversedZBuffer:" + SystemInfo.usesReversedZBuffer,
            });
        return string.Join("\n", list.ToArray());
    }

    // Use this for initialization
    void Start () {
    
    
        graphicsAPI_Text.text = MyDump();
    }
}


各个设备中的表现


Unity 编辑中

在这里插入图片描述


夜神模拟器中

在这里插入图片描述


小米10

在这里插入图片描述


OPPO A5

可以看到 OPPO A5 是显示异常的
在这里插入图片描述


BRP 中没看到有相关的解决

毕竟 BRP 是未来不推荐的方案
所以出现这种问题,建议还是使用 URP

本来想看看 project setting 中的 graphics, quality 有无相关的深度精度设置,经过一番搜索与项目配置查找,都没有找到相关内容

  • goolgle : how to improve precision in unity shaderlab

然后在 官方文档中 Cameras and depth textures 找到一些精度相关的说明

在这里插入图片描述

查找过的配置:

  • ProjectSetting->Player->OtherSetting->Rendering - 没有相关
  • ProjectSetting->Player->OtherSetting->Resolution and Presentation - 没有相关
  • ProjectSetting->Graphics 下尝试将所有的 Tier Settings 都设置到最高,也不行
  • Shader 中添加:#pragma fragmentoption ARB_precision_hint_nicest 也不行
  • Shader 中修改 _CameraDepthTexturefloat 的纹理采样器设置也不行,比如:uniform sampler2D_float _CameraDepthTexture;

URP 中有解决

这写问题在 早期的 URP 也有出现,比如这帖子:Android depth texture precision issue. - 帖主是再:Unity 2019.3.6f1 URP 7.2.1,在 URP:7.4.1 修复了

大概就是:application 层,对 _CameraDepthTexture 的纹理对象格式的设置(精度设置)

还有 shader 中的精度声明

在 BRP 中并没有对应的可控性,这在 URP 是可控的,所以 URP 可以解决此问题


另外,高版本的 unity 也看到有:shader precision mode 的设置

下面是:2022.1.4f1 的截图
在这里插入图片描述


导致这些精度问题,一般还与 Camera 的 近截面远截面 的差值有关,差值越大,那么越容易出现这个问题

而这个项目在我来之前,他们的模型比例等相关制作的缩放都是异常的,比如:500 scale,x,y,z

然后 Camera 的 near plane, far plane 都只能设置很大,比如:near : 0.1, far : 10000,那么精度的值肯定大大受限


References

猜你喜欢

转载自blog.csdn.net/linjf520/article/details/125522428