Unity、Ps、normalMap下,根据制作真实法线贴图(文中包含:偏振法线数据集、高度图)

文章不长,请耐心看完。会有收获~~~~~~~~~~~~~~~~~~~~~~~

简介:

SFM(Shape From Move),SFS(Shape from Shading),SFP(Shape From Polarization)等技术均是三维重建常用的方法,但是无论选择哪一种技术,在三维重建的过程中都无法避免法线。而为了更好的存储与纹理移植,法线贴图应运而生。

法线贴图存储法线的形式为:RGB通道分别存储法线的XYZ轴坐标,即将物体表面某一点的向量信息保存至图像通道中。


由于我是做SFP的,以下为三个具有代表意义的数据集:

文1提出了真实场景下环境的偏振数据集(含真实法线)

文1:export.arxiv.org/pdf/2112.11377.pdf

代码1:GitHub - ChenyangLEI/sfp-wild: [CVPR2022] Shape from Polarization for Complex Scenes in the Wild

数据集1:https://hkustconnect-my.sharepoint.com/:u:/g/personal/cqiaa_connect_ust_hk/EW7tfbO_I3dHjfp8H3ZsLikBwPaFL72ypZYMQTs_YifPwA?e=OFFk3e&download=1

文2提出利用深度学习解决偏振法线歧义性,并公布纹理较简单的小物体数据集(含真实法线)

文2:ecva.net/papers/eccv_2020/papers_ECCV/papers/123690545.pdf

代码2:GitHub - UCLA-VMG/DeepSfP
数据集2:https://drive.google.com/file/d/1EtjfMTfpanJotH92GFz300X_ZEmGXuqr/view

文3为清华大学团队公布的透明物体偏振数据集(含真实法线)

文3:arxiv.org/pdf/2208.11836.pdf

代码3:GitHub - shaomq2187/TransPIR: Repo for Polarimetric Inverse Rendering for Transparent Shapes Reconstruction

数据集3:https://cloud.tsinghua.edu.cn/f/2feaea15e9094941b4bd/?dl=1

那么,这些数据集中的法线贴图真实值是如何得到的呢?博主对网上现有的法线贴图获取方式进行了一个汇总。

法线贴图获取方式

网上现有的法线贴图获取方式,可分为以下四类:

1.一种说法,利用blender、3dmax等三维建模软件,进行高模、低模等操作,最后烘培出出法线贴图。如果你想尝试一下的话,可以参考以下贴。

Blender法线贴图(贴1)

(34条消息) blender烘焙法线贴图_blender 法线贴图_danad的博客-优快云博客

3dmax法线贴图(贴2)

(34条消息) 什么是法线贴图 今天教你如何制作法线贴图_法线图_langgesanshiyi的博客-优快云博客

但是,很可惜。贴1对法线贴图的制作描述的貌似不是很清晰,而贴2中有的图像看不到。

2.利用ps,对图像进行法线贴图操作,这种方法的效果更倾向于sobel边缘检测出来的结果(边缘轮廓特别明显,但是物体表面较平扁)。但是,Ps对于法线贴图的制作仍具有最高的兼容性,因为ps可打开多种格式。下图为Ps中的结果图,从左至右分别为高度图,高度结果法线图,强度图,强度结果法线图。

具体实现可参考以下贴(34条消息) Shader Graph2-使用PS生成正确的法线贴图_ps生成法线图_艺菲的博客-优快云博客

(34条消息) 如何通过Photoshop根据纹理贴图轻松获得法线贴图_如何通过纹理生产人物法线_qq_21315789的博客-优快云博客

3.利用normal在线生成法线贴图,这个网站的功能还是很强的。它可以根据高度图生成相应的法线贴图,但是经对比,它与真实值之间仍存在一定的差距。单不可否认,这个网站还是有很大的实用性。注意该网站支持的图像为高度图获取法线图,而输入强度图像时效果较差。下面是博主在该网站上进行测试的结果图

具体实现可参考以下贴:(34条消息) 一个免费在线法线贴图生成器(Normal Map Generator)_在线转法线_开发游戏的老王的博客-优快云博客

4.经测试,unity在得到法线贴图时,其效果优于以上三种方法。它的具体操作步骤如下:
首先,我们输入的是强度图像,它是2d的。其次,我们将它拖拽至assets中并左键单击,可以在inspector(检查器)中找到texture type选择normal map 。最后,单击右下角apply。下面是输入为强度图像的结果图,从左至右分别为强度图,不选取gray,选取gray。

 下面是输入为高度图时的结果图,从左至右分别为强度图,不选取gray,选取gray,数据集中真实法线贴图(已mask)。

可以看出,当输入为高度图,且选择gray时,得到的法线贴图与数据集中的真实值最为相似。

最后,我们对于同一张高度图像,进行了ps、normal在线网站、unity之间的对比。可以看出,在unity中得到的法线贴图最符合物体表面,且结果具有表面突出信息。下面从左到右分别为高度图、ps结果图、normal在线网站结果图、unity结果图、数据集中真实法线图。

unity不支持将法线贴图直接导出为png格式,当我们直接对法线贴图进行截图时,得到的图像会被压缩,所以将纹理法线导出为png格式仍被需要。下面是利用C#联合unity实现将法线贴图导出为png格式的代码。

首先,我们需要在菜单栏下windows里面新增一个名为‘Normal Map Exporter ’的按钮。

实现这一功能的代码为

GUILayout.Label("Normal Map Exporter", EditorStyles.boldLabel); // 在编辑器窗口中显示标题

其次,点击此按钮会弹出如下界面。

将图像托至红框处,在点击‘Export as PNG’ 便可弹出对话框保存至本地。实现这个功能的代码如下

normalMapTexture = (Texture2D)EditorGUILayout.ObjectField("Normal Map Texture", normalMapTexture, typeof(Texture2D), false); // 在编辑器中创建一个字段,用于选择法线贴图纹理

if (GUILayout.Button("Export as PNG")) // 在编辑器中创建一个按钮,点击时触发导出操作
  。。。。。。。。。。

 在点击‘Export as PNG’时会进行,读取纹理法线的相关操作,代码如下

if (GUILayout.Button("Export as PNG")) // 在编辑器中创建一个按钮,点击时触发导出操作
        {
            if (normalMapTexture != null) // 检查是否已选择法线贴图
            {
                string texturePath = AssetDatabase.GetAssetPath(normalMapTexture); // 获取法线贴图在项目中的路径
                Debug.Log("Texture Path: " + texturePath);
                TextureImporter textureImporter = (TextureImporter)AssetImporter.GetAtPath(texturePath); // 获取法线贴图的导入器

                // 检查纹理是否已设置为法线贴图类型
                if (textureImporter.textureType != TextureImporterType.NormalMap)
                {
                    textureImporter.textureType = TextureImporterType.NormalMap; // 将纹理类型设置为法线贴图
                    textureImporter.SaveAndReimport(); // 保存和重新导入纹理
                }

                // 将颜色空间设置为线性
                textureImporter.sRGBTexture = false;
                textureImporter.SaveAndReimport();

                // 创建一个临时的RenderTexture
                RenderTexture renderTexture = RenderTexture.GetTemporary(normalMapTexture.width, normalMapTexture.height, 0, RenderTextureFormat.Default, RenderTextureReadWrite.Linear);
                Graphics.DrawTexture(new Rect(0, 0, renderTexture.width, renderTexture.height), normalMapTexture);

                RenderTexture previous = RenderTexture.active;
                RenderTexture.active = renderTexture;

                // 创建一个Texture2D用于导出
                Texture2D exportTexture = new Texture2D(normalMapTexture.width, normalMapTexture.height, TextureFormat.RGBA32, false);
                exportTexture.ReadPixels(new Rect(0, 0, renderTexture.width, renderTexture.height), 0, 0);
                Debug.LogWarning("exportTexture:"+ exportTexture); // 若未选择法线贴图,输出警告信息
                exportTexture.Apply();

                RenderTexture.active = previous;
                RenderTexture.ReleaseTemporary(renderTexture);

弹出的保存图像窗口为

注意,保存图像的路径应为Assets下。实现的相关代码为

// 将Texture2D保存为PNG
                byte[] bytes = exportTexture.EncodeToPNG();
                string path = EditorUtility.SaveFilePanel("Export Normal Map", "", "NormalMap.png", "png"); // 弹出文件保存对话框,选择保存路径和文件名
                if (!string.IsNullOrEmpty(path))
                {
                    System.IO.File.WriteAllBytes(path, bytes);
                    AssetDatabase.Refresh(); // 刷新资源数据库,使新的PNG文件在项目中可见
                    Debug.Log("Normal Map exported as PNG: " + path); // 在控制台输出导出路径

代码可在这里直接下载(35条消息) 【免费】unity中将法线贴图导出png格式的代码,可直接运行C#实现非截图!!!截图会压缩图像质量资源-优快云文库

如有不正之处,欢迎指出。

同时欢迎关注,下一步尝试由三维模型的某一视角得出高度图。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值