【Unity URP】Rendering Debugger和可视化MipMap方案

这篇具有很好参考价值的文章主要介绍了【Unity URP】Rendering Debugger和可视化MipMap方案。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

写在前面

最近开始学习Unity性能优化,是结合了《Unity游戏优化》这本书和教程《Unity性能优化》第叁节——静态资源优化(3)——纹理的基础概念一起学习。在学习纹理优化部分时候遇到了问题,固定管线下Unity的Scene窗口有一个可视化Mipmap的渲染模式:

【Unity URP】Rendering Debugger和可视化MipMap方案

而这批Miscellaneous模式的选项在URP下相同位置没了:

【Unity URP】Rendering Debugger和可视化MipMap方案

又比较需要这个便捷的查看方法!于是搜一下想看看有没有出一些插件之类的,突然搜到了大概20年也有小伙伴提出这个问题:

Missing Scene view Draw Modes (Mipmaps, Overdraw, etc.) - Unity Forum

【Unity URP】Rendering Debugger和可视化MipMap方案

底下Unity技术人员回复了,大概意思就是会加入Rendering Debugger来实现之前固定管线下的D

rawMode的一些功能: 

【Unity URP】Rendering Debugger和可视化MipMap方案

于是就发现了Rnedering Debugger功能,What's new in URP 12 (Unity 2021.2) | Universal RP | 12.0.0

【Unity URP】Rendering Debugger和可视化MipMap方案

之前URP下做东西的时候完全没有注意和使用过!一起来简单看看:

Rendering Debugger

非常方便了!比如Material的一些查看,可以单独看albedo的效果:

【Unity URP】Rendering Debugger和可视化MipMap方案

比如OverDraw:

【Unity URP】Rendering Debugger和可视化MipMap方案

曾经固定管线下的级联阴影、Alpha通道等的一键预览都有了!但是还是没有Mipmap。

其他版本的URP该怎么办?

小插曲,在Rendering Debugger没出来前,这位大佬Scene View Debug Modes in the Unity URP — John Austin甚至自己做了个插件:

【Unity URP】Rendering Debugger和可视化MipMap方案

虽然后续URP已经提供了rendering debugger,但是这个把shader添加进debug里的整个框架我们是可以参考过来的。 

讨论Build-in下Scene视图的Mipmaps

其实Mipmap可视化已经有人总结过了:Re0-TA成长笔记 01关于Mipmap问题

而且asset store有免费的类似插件:Colored Mipmap Texture - Visualized Checker

【Unity URP】Rendering Debugger和可视化MipMap方案

还有其他的方法,要么方法我看不太懂,,要么颜色太多我感觉也不需要那么多颜色,只是想把Mipmap视图作为优化纹理的小工具。我希望在URP下也能实现固定管线那种简单的蓝/红色的Mipmap显示效果,实现方法尽量的简单一点,固定管线下就这样简单:

【Unity URP】Rendering Debugger和可视化MipMap方案

场景很简陋(之前学习入门精要的build-in项目~),也算体现了大概吧,当纹理大小刚刚好的时候展示的就是纹理的样子,纹理太小了精度不够就会是蓝色,纹理太大精度过大就会是红色!

因为比较好奇,build-in下的Scene视图的Mipmap到底是怎么运行的?物体shader里的贴图一定不只有一张主纹理,他的法线纹理、金属度等纹理都会参与Mipmap,这个大小是综合所有贴图判断的吗?还是只关注主要的albedo贴图?

我们测试一下,拿之前学习法线映射的shader为例,shader有两张纹理,albedo和normal,大小均为2048,显然都过大了,所以Mipmap视图下整体是红色:

【Unity URP】Rendering Debugger和可视化MipMap方案

现在把albedo贴图改为32,变成蓝色了!:

【Unity URP】Rendering Debugger和可视化MipMap方案

如果我们只改normal的大小为32,albedo那张不变呢?没有变化!还是红色:

【Unity URP】Rendering Debugger和可视化MipMap方案

这就初步说明,固定管线下这个Mipmap level判断依据,是根据shader中的MainTex(主纹理)来判断的,而且物体shader的SubShader的RenderType一定要有,才能参与这个Scene视图下Mipmap的红蓝判断:

【Unity URP】Rendering Debugger和可视化MipMap方案

还需要确定一点,就是这个Mipmap渲染的shader到底怎么获取纹理的?我们再测试一下,如果shader里如果主纹理命名不是默认的_MainTex,而是_BaseTex的话:

【Unity URP】Rendering Debugger和可视化MipMap方案

场景中之前的那个物体又变蓝了!

【Unity URP】Rendering Debugger和可视化MipMap方案

好了,到这里我们可以初步推断:

Build-in管线下,Scene View里的Mipmaps可视化,只针对shader主纹理命名为_MainTex的物体有效,且只关注_MainTex一张贴图的大小是否合适,其余的法线纹理等其他贴图不受关注

探讨URP下Mipmap可视化方案

初步猜测:如果我只想要简单的红蓝检测效果,且实践方法尽量简单,我必须要在URP下能够访问所有项目的主纹理,然后单独做一个ViewDebug_Mipmaps的shader,挂在View视图窗口。

紧接着,找资料突然就看到了11年的时候就有人提出了一种可视化Mipmap方案:

A way to visualize mip levels · Aras' website (aras-p.info)

【Unity URP】Rendering Debugger和可视化MipMap方案

有意思的是在查看Build-in的Debug.hlsl文件时,发现Unity的可视化方案也是参考了之前的那个文章(Unity的Debug.hlsl文件):

【Unity URP】Rendering Debugger和可视化MipMap方案

上面那个人的主要shader如下:

struct v2f {
    float4 pos : SV_POSITION;
    float2 uv : TEXCOORD0;
    float2 mipuv : TEXCOORD1;
};
float2 mainTextureSize;
v2f vert (float4 vertex : POSITION, float2 uv : TEXCOORD0)
{
    v2f o;
    o.pos = mul (matrix_mvp, vertex);
    o.uv = uv;
    o.mipuv = uv * mainTextureSize / 8.0;
    return o;
}
half4 frag (v2f i) : COLOR0
{
    half4 col = tex2D (mainTexture, i.uv);
    half4 mip = tex2D (mipColorsTexture, i.mipuv);
    half4 res;
    res.rgb = lerp (col.rgb, mip.rgb, mip.a);
    res.a = col.a;
    return res;    
}

OHHHH,他的实现思路差不多就是我的意思!shader里的mainTextureSize,实际上就是URP下shader里我们能默认获取得到的BaseMap_TextureSize,其余的操作只是为了能根据距离动态判断纹理大小是否合适,根据判断结果给上红蓝色。

那我们就开始吧!首先是确定,怎么获取纹理?想起来了,可以从URP下自带的Rendering Debugger入手:

看看Rendering Debugger的逻辑

简单一点,我们打开URP的文件夹,搜索Debug

【Unity URP】Rendering Debugger和可视化MipMap方案

成功定位到Debugging3d.hlsl:

Debugging3D.hlsl

具体内容就不一句一句来了,单独挑一个,Material的:

【Unity URP】Rendering Debugger和可视化MipMap方案

你会发现!原来Debugger的逻辑并不是重新自己有一套shader,而是直接拿SurfaceData的东西用,输出想要的项就行了。

SurfaceData

之前扒URP的PBR Shader的时候就已经见过他了,SurfaceData是在SurfaceData.hlsl定义的结构体:

【Unity URP】Rendering Debugger和可视化MipMap方案

然后在LitInput.hlsl中定义了一个InitializeStandardLitSurfaceData()函数,去初始化SurfaceData:

【Unity URP】Rendering Debugger和可视化MipMap方案

尝试输出Surface.albedo

刚好我作为联系我有想要优化的项目,那就直接在项目中写个shader看看能不能成功提取SurfaceData.albedo吧!写个shader:

Shader "Debug/Debug Albedo"
{
    SubShader
    {
        Tags{"RenderType" = "Opaque" "RenderPipeline" = "UniversalPipeline"}

        Pass
        {
            HLSLPROGRAM
            
            #pragma vertex LitPassVertex
            #pragma fragment frag

            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/SurfaceData.hlsl"
            #include "Packages/com.unity.render-pipelines.universal/Shaders/LitInput.hlsl"
            #include "Packages/com.unity.render-pipelines.universal/Shaders/LitForwardPass.hlsl"

            float4 frag(Varyings input) : SV_TARGET {

                UNITY_SETUP_INSTANCE_ID(input);
                UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input);

                #if defined(_PARALLAXMAP)
                #if defined(REQUIRES_TANGENT_SPACE_VIEW_DIR_INTERPOLATOR)
                    half3 viewDirTS = input.viewDirTS;
                #else
                    half3 viewDirTS = GetViewDirectionTangentSpace(input.tangentWS, input.normalWS, input.viewDirWS);
                #endif
                    ApplyPerPixelDisplacement(viewDirTS, input.uv);
                #endif

                SurfaceData surfaceData;
                InitializeStandardLitSurfaceData(input.uv, surfaceData);
                
                return float4(surfaceData.albedo, 1);
                
            }
          
            ENDHLSL
        }
    }

}

参考上面自己Debug的框架,给他做成开关放在Scene下的DrawMode里:

【Unity URP】Rendering Debugger和可视化MipMap方案

结果,,,Scene是全黑的,并没有单独展示Albedo:

【Unity URP】Rendering Debugger和可视化MipMap方案

哪里出错了?想起来,不会是因为BaseMap命名和采样的问题吧。为了测试我的想法是否正确,场景中拖个正方体,给他一个简单的shader,shader严格按照BaseMap来:

【Unity URP】Rendering Debugger和可视化MipMap方案

同样的DrawMode选择Albedo,居然出现了!

【Unity URP】Rendering Debugger和可视化MipMap方案

果然,验证了我的猜想。检查一下项目里的shader,发现shader都是拿ASE实现的,,,转化的命名什么的都有点混乱,,,

再拿个之前搭的模型为例吧:

【Unity URP】Rendering Debugger和可视化MipMap方案

同样的Shader:

【Unity URP】Rendering Debugger和可视化MipMap方案

成功了!调出了albedo,啊,可视化的途径我们算是找到了,接下来就是实现了!

URP下实现Mipmap可视化

给texture每个mip层赋值

这其实是最关键的一步——我们需要有图可采样成颜色。

Tutorial: Creating and modifying custom mipmaps - Texture Tools - NVIDIA Developer Forums

我尝试过Unity创建纹理,也尝试过PS、GIMP生成dds图,但是这俩好像只能打开dds却不能编辑每一个Mip层的颜色!!!

【Unity URP】Rendering Debugger和可视化MipMap方案

于是另寻他路:dds的目的是给每个mipLevel给一个颜色值,那我们直接获取mipmap的level,根据这个level值输出对应的颜色不就好了,也就是shader里实现这行采样代码:

half4 mip = tex2D (mipColorsTexture, i.mipuv);

这里注意一下,tex2D的本质是什么?这是Unity提供的一个采样器,输入需要采样的纹理及对应的uv值,会进行采样,并根据纹理的设置生成mipmap。这里要关注另一个采样函数:tex2Dlod,这个是可以根据传入uv的.w分量信息指定mipmap层的。随便搜一下tex2Dlod的原理,就能明白了,比如这篇文章:MipMap的LOD实现原理 - 知乎里写的:

float mipmapLevel(float2 uv, float2 textureSize) 
{    
 float dx = ddx(uv * textureSize.x);    
 float dy = ddy(uv * textureSize.y);   
 float d = max(dot(dx, dx), dot(dy, dy));
 return 0.5 * log2(d);//0.5是技巧,本来是d的平方。
} 

我直接在fragment shader里计算:

// 直接自己计算lod,参考tex2DLod
                float2 mipUV = o.uv * o.mainTextureSize/ 8; // 参考文章的方案
                float dx = ddx(mipUV); // 
                float dy = ddy(mipUV);
                float px = 32 * dx;
                float py = 32 * dy;
                float lod = 0.5 * log2(max(dot(px, px), dot(py, py)));

再写个函数,根据传入的lod值lerp我的颜色,颜色取值来自上面的那篇文章:

// 根据当前纹理的Mip层值返回给定颜色
            float4 GetCurMipColorByManualColor(float mipLevel)
            {

                if(mipLevel==0) // 纹理压根没有开启mipmap
                {
                    return real4(0.0,0.0,1.0,1); // 给.a为0,即baseMap
                }
                else
                {
                    if(mipLevel < 1 ) // 代表着纹理太小了,给个蓝色
                    {
                        return lerp(real4(0.0,0.0,1.0,1),real4(0.0,0.0,1.0,0.8),mipLevel);
                    }
                    else if (mipLevel <2)
                    {
                        return lerp(real4(0.0,0.0,1.0,0.8),real4(1,1,1,0), mipLevel-1);
                    }
                    else if(mipLevel <3) // mip的正正好,于是.a值给0,意味着纹理此时恰到好处
                    {
                        return lerp(real4(1,1,1,0),real4(1.0,0.7,0.0,0.2),mipLevel-2);
                    }
                    else if(mipLevel <4)
                    {
                        return lerp(real4(1.0,0.7,0.0,0.2),real4(1.0,0.3,0.0,0.6),mipLevel-3);
                    }
                    else if(mipLevel <5)  // mip太多了吧,意味着纹理太大了!因此给个更红的颜色
                    {
                        return lerp(real4(1.0,0.3,0.0,0.6),real4(1.0,0.0,0.0,0.8),mipLevel-4);
                    }
                    else
                    {
                        return real4(1.0,0.0,0.0,0.8); // mip了超大,直接给正红色,.a直接点满,完全为debug的颜色
                    }
                }
            }

接着fragment shader里:

float3 baseColor = surfaceData.albedo;
                float4 debugColor = GetCurMipColorByManualColor(lod);
                float4 res;
                
                res.rgb =lerp(baseColor.rgb, debugColor.rgb, debugColor.a); //由debugColor.a控制插值
                res.a = 1;
                return res;

就是说,到这里就已经实现了!具体怎么把他搬进Scene视图下,前面列举了一个URP下别人实现Albedo可视化的框架,我是直接拿过来用了,他给了源码,所以脚本这里就不过多的介绍。

效果展示

放上一个跟固定管线里的相同模型、贴图的场景的mipmap可视化对比,左边是固定管线下,右边是我实现的:

【Unity URP】Rendering Debugger和可视化MipMap方案

【Unity URP】Rendering Debugger和可视化MipMap方案

可以看出在显示上是有一定偏差的,因为Unity内部到底是怎么做mipmap可视化,颜色如何规定的?颜色和mip层的关系是怎样的?没在源码中找到太多的依据。

但基本上算是实现了!虽然shader用了很多个if,但是只是一个debug环节,不用太考虑效率问题。总的来说这个方案学习过程中自己使用起来还是足够的!

文章写的很潦草,涉及到的内容太扩散了,其实也是我实现过程中的心路历程,希望看到这里的你能看懂!!!!文章来源地址https://www.toymoban.com/news/detail-442003.html

到了这里,关于【Unity URP】Rendering Debugger和可视化MipMap方案的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Unity行为树可视化编辑器开发

    在ARPG项目的开发过程当中,要涉及到NPC的AI系统,一般来说,简单的AI行为使用状态机即可比较好的实现,但如果NPC的行为稍微一复杂,那么使用状态机来实现就会比较难维护,并且后期工作量会随着NPC状态的增加而成倍增加。 这时就可以考虑使用行为树来实现NPC的AI,行为

    2024年02月11日
    浏览(44)
  • 【Unity之IMGUI】—编译模式下控件可视化及其封装

    👨‍💻个人主页 :@元宇宙-秩沅 👨‍💻 hallo 欢迎 点赞👍 收藏⭐ 留言📝 加关注✅! 👨‍💻 本文由 秩沅 原创 👨‍💻 收录于专栏 :UnityUI篇实战 缺点1:无法在编译过程进行可视化调整 缺点2:无法分辨率自适应 此图可忽略 UML类图 性能优化代码 完整代码: 按钮封装代

    2024年02月10日
    浏览(42)
  • unity中添加中文字体实现UI可视化设计

    第一步:打开C盘下的Windows中的Fonts字体并选择一款喜欢的字体。路径为:C:WindowsFonts 第二步:将复制的字体放到unity项目下的Scenes文件下; 第三步:新建一个txt文档来存储中文字体(不存储在txt文档中的字体在unity中是显示不出来的),可仅存储自己的需要的中文,也可存

    2024年02月11日
    浏览(59)
  • unity 曲线可视化图表制作(lineRenderer + 贝塞尔曲线)

    需求要实现一个动态变化的曲线 思路: 分为两部分:画线和平滑曲线 首先解决画线问题: 1.lineRenderer 2.texture的setpixel 肯定选已经做好的轮子1啦 平滑曲线思路: 1.抛物线 2.贝塞尔曲线 抛物线做连续的曲线太抽象了 肯定选贝塞尔曲线 先了解一下贝塞尔曲线 一次贝塞尔 对应

    2023年04月08日
    浏览(51)
  • Unity 可视化节点编辑器(GraphView、编辑器扩展)

      前几天把导师的项目打包发布交了一稿,这半个星期除了再把项目缝缝补补外(说实话项目做到后边实在有些无聊,都是些琐碎的东西而且自己也学不到什么,纯粹是 浪费 消磨时间)无聊逛Unity商店发现了个有意思的东西,说实话一开始我以为只是单纯绘制的2D动画:

    2024年02月12日
    浏览(63)
  • [Unity] GraphView 可视化节点的事件行为树(三) GraphView介绍

    目录 前言 GraphView的节点(Node)和端口(Port) GraphView的边(Edge) 关联Inspector窗口,显示数据 增加节点操作 构建节点图 删除与修改节点操作 创建节点的新建菜单栏 GraphView 复制粘贴操作实现         前置章节: [Unity] 使用GraphView实现一个可视化节点的事件行为树系统(序章/Gith

    2023年04月27日
    浏览(43)
  • 球谐函数的一些理解(基于3DGS)+Unity的可视化

    1.背景 读3DGS的相关文章的时候提到了一些球谐函数的概念,有些不理解,结合下面的文章做一些扩展 2.参考链接 球谐函数介绍(Spherical Harmonics) - 知乎 (zhihu.com) 球谐函数一:基础理论 - 知乎 (zhihu.com) 3.细节 这里是整篇文章的最关键的举例子解释,但是由于对极坐标不太了解

    2024年04月08日
    浏览(72)
  • 【Unity之IMGUI脚本封装】—编译模式下控件可视化及其封装

    👨‍💻个人主页 :@元宇宙-秩沅 👨‍💻 hallo 欢迎 点赞👍 收藏⭐ 留言📝 加关注✅! 👨‍💻 本文由 秩沅 原创 👨‍💻 收录于专栏 :UnityUI篇实战 缺点1:无法在编译过程进行可视化调整 缺点2:无法分辨率自适应 此图可忽略 UML类图 性能优化代码 完整代码: 按钮封装代

    2024年02月15日
    浏览(61)
  • [Unity] GraphView 可视化节点的事件行为树(一) Runtime Node

            这个框架最近自己终于补充完成了,使用文档和源码已经放在了Github上,可以在之前的文章中找到: [Unity] 使用GraphView实现一个可视化节点的事件行为树系统(序章/Github下载)_Sugarzo的博客-CSDN博客_unity graphview                  本文将开始介绍Runtime部分的

    2024年02月07日
    浏览(37)
  • Unity可视化编程Visual Scripting学习笔记2:说你好(hello world)

    1.在Project面板新建Script Graph 2.给物体挂上该Graph 3.在Graph面板添加On Start事件节点(相当于脚本中的Start生命周期) 从Start绿色箭头出拉出,并创建print方法节点 可以看到print方法节点需要一个Message参数 从print方法节点的Message圆点拉出并选择String     在String数据节点中输入数

    2024年02月13日
    浏览(48)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包