【流程向】模型复原与Unity渲染

article/2025/7/19 9:23:23

项目简述

简单记录下学校里的一个项目,涉及到对/何家村遗宝/的模型复原,记录一下模型制作的全流程,同时涉及到Unity中一些优化画面的技术点。项目中渲染效果优先,没有怎么考虑性能。

流程:Blender高低模与展UV -> Substance Painter贴图制作 -> PS贴图编辑 -> Unity渲染


Blender高低模与展UV

此次项目之前DCC使用的一直是C4D,借着这次机会学习了一波Blender,这部分涉及的内容均是一些备忘技巧。(参考视频在后面)

  • 一些好用的Add-ons,从名字应该能大概了解到用途:
  1. Object: Bool Tool; 
  2. Mesh: LoopTools; 
  3. Mesh: AutoMirror;
  4. Import-Export: Import Image as Planes;
  • Object关于平面镜像(无修改器):
  1. Shift+C,游标归位原点
  2. 选中被镜像的物体,Shift+D复制
  3. Pivot Point设为3D_Cursor
  4. 选中复制出来的物体,Control+M,拖动鼠标中键镜像
  • 内置雕刻笔刷的适用情景(个人习惯)
  1. Blob -> 可用于浮雕等凸起平面,反向凹陷
  2. Pinch -> 捏边,增加细节,及时Control+R平均布线
  3. Grab -> 大体修形
  4. Inflate -> 对凸起内容进行膨胀,鼓起,增加体积,反向同理
  5. 注意:使用Layer、Clay等笔刷时小心模型背面,如果太薄可能编辑前面时同时受到影响。

  • Blender工作流

        首先低面体建模之前设置一下视图的渲染,有效提升幸福感(确信

        好像比较规范的高低模工作流是使用Multi-Resolution Modifier,因为没有来得及细研究,并且项目只涉及到引擎用的低模和烘焙用的高模,所以对于上面的牛来说,直接由高模添加Remesh修改器,使用其中的Sharp项更好的保留细节;对于左边的马来说,主体部分直接使用低面体加表面细分修改器作为低模,雕刻信息交由贴图烘焙。

        UV展开的比较草率,尽量保证了接缝处在看不到的地方,并没有苛求通过缩放来最大程度填满uv,painter里直接出高分辨率贴图来填补,也没有管uv拉伸的程度。此外,由于UV组还没有搞明白,像是牛鼻子这些部件实际上是另外的一个模型,本质上在Unity中一个模型Prefeb里是由好几个分开的mesh组成的。

        雕刻部分应该只是刚能雕出东西的水平。。上面的马高模细节并没有很多,却搞了700万个顶点出来,进入雕刻模式要卡一下,要是手滑Tab进了编辑模式要20G的内存占用,M1Pro的16G内存可以说是完全不够用,疯狂Swap,一个星期没关机看硬盘读写有1.4T。。

Substance Painter 贴图制作

        绘画流程对于一个不会美术的人来说可以说是很痛苦了,好在大多可以通过一些讨巧的手段获得还不错的效果。以下面这个马的主体为例。

        这个壶的主体是一个没有什么细节的简单模型,直接使用雕刻好的高模主体烘焙贴图,会得到与马有关的Normal,AO,Curvature,Thickness等信息。不过注意,此时AO是不会像上图中一样有链条等遮挡信息。保存当前的AO,单独导出一个包含所有部件的模型并烘焙AO,得到链条等AO信息,再将两张图在PS中变暗处理即合成最终AO。

        过程中还遇到另外一个问题,以下面这个低模高模均没有雕刻细节的壶盖举例。这个模型上表面的花瓣形状的凸起是新建带有Height信息的图层,并加以遮罩实现的,所以由高模烘焙的法线和曲率贴图并不存在这个信息,智能材质也就不能据此来创建磨损等细节。

        解决方法是直接导出法线贴图,也就是将高度信息烘焙到法线上去,然后再将得到的法线贴图放入烘焙贴图的槽内,最后去除为烘焙指定的高模,只勾选World Normal,Curvature,AO即可以当前模型的法线进行烘焙了。同样的原理也用在了下面这些小狮子的制作,十几只形态各异,而书中给了轮廓描边,于是将它们转换成贴图倒入SP,再进行了上面的操作。

        此外其他的几个注意点:

        低模在导出的过程中注意在Blender里设置为Shade_Flat,不然导进Painter里也不是平滑的。

        由于金属部分在Unity中直接使用了Standard Shader,所以自己进行了输出贴图配置。

Unity模型渲染 

        最终效果展示比较简单,主要是向着这个视频中的交互,仅仅涉及到天空球的切换和旋转观看文物,所以这部分主要围绕天空盒的更换以及天空盒对物体的受光展开。

玉石Shader

        制作的这几个模型中,大部分都是金属材质,可以直接使用Unity的Standard Shader,可以根据启用不同的Reflection Probes呈现出不同的受光效果。不过为了做这个玉的效果,很自然就会想到SSS,Unity资源商店发现了付费的Shader,不过对于玉石这种并没有很透的物体,又查到了DICE模型的实现,在将示例的Surface Shader整合到和庄懂老师学习的Shader中,得到了这个玉石Shader。

        这部分的Shader分成两个Pass,第一个Pass处理环境光照和直射光,使用Phong光照模型完成基础光照,使用球谐光照作为环境光源,采样unity_SpecCube0作为环境反射。

        可以看到下面代码中环境光反射部分尝试了指定Cubemap贴图、指定Hdr贴图的方法,最后找到了unity的api,果断用Reflection Probe最香。

float4 fragOne(VertexOutput i) : COLOR
{float3x3 TBN = float3x3(i.tDirWS, i.bDirWS, i.nDirWS);float3 nDirTS = UnpackNormal(tex2D(_NormTex, i.uv0)).rgb;// 切线空间法线float3 nDirWS = normalize(mul(nDirTS, TBN));                        // 世界空间法线 float3 vDirWS = normalize(_WorldSpaceCameraPos.xyz - i.posWS.xyz);  // 世界空间视线float3 vrDirWS = reflect(-vDirWS, nDirWS);                          // 视线反射方向          float3 lDirWS = _WorldSpaceLightPos0.xyz;                           // 光线方向float3 lrDirWS = reflect(-lDirWS, nDirWS);                          // 光线反射方向float ndotl = dot(nDirWS, lDirWS);                                      float vdotr = dot(vDirWS, lrDirWS);float vdotn = dot(vDirWS, nDirWS);float3 var_MainTex = tex2D(_MainTex, i.uv0).rgb;float var_AOTex = tex2D(_AOTex, i.uv0);// 环境光反射部分//Cubemap反射// float3 var_Cubemap = texCUBElod(_Cubemap, float4(vrDirWS, lerp(_CubemapMip, 0.0, var_SpecTex.a))).rgb;//手动全景贴图反射// float3 dir = mul(RotationY(_Rotation), vrDirWS);// float2 uv = float4((atan2(dir.x, dir.z) / UNITY_PI + 1.0)*0.5, 1.0-acos(dir.y) / UNITY_PI;// float3 var_SkyTex = tex2Dlod(_SkyTex, uv, 0.0 ,lerp(_CubemapMip, 0.0, var_SpecTex.a)))//采样Reflection Probe反射float4 var_specTex = UNITY_SAMPLE_TEXCUBE_LOD(unity_SpecCube0, vrDirWS, 0.0);// 光照模型(直接光照部分)float3 baseCol = var_MainTex.rgb;                   // 模型基色float lambert = max(0.0, ndotl);                    // 兰伯特模型float phong = pow(max(0.0, vdotr), _SpecPow);       // Phong高光float shadow = LIGHT_ATTENUATION(i);                // 接受的Shadowfloat3 dirLighting = (baseCol * lambert + phong) * _LightColor0 * shadow;// 光照模型(环境光照部分)half3 envCol = ShadeSH9(float4(normalize(nDirWS.xyz), 1.0));// 球协环境光float fresnel = pow(max(0.0, 1.0 - vdotn), _FresnelPow);          // 菲涅尔float occlusion = var_AOTex;                                      // 采样环境光遮蔽float3 envLighting = (baseCol * envCol * _EnvDiffInt + var_specTex * fresnel * _EnvSpecInt) * occlusion;// 返回结果float3 finalRGB = dirLighting + envLighting;return float4(finalRGB, 1.0);
}

        第二个Pass模拟SSS效果,根据Thickness贴图提高模型局部亮度,代码透明部分参考GDC2011发表

float4 fragTwo(VertexOutput i) : COLOR
{float3x3 TBN = float3x3(i.tDirWS, i.bDirWS, i.nDirWS);float3 nDirTS = UnpackNormal(tex2D(_NormTex, i.uv0)).rgb; float3 nDirWS = normalize(mul(nDirTS, TBN));                           float3 vDirWS = normalize(_WorldSpaceCameraPos.xyz - i.posWS.xyz); float3 var_MainTex = tex2D(_MainTex, i.uv0).rgb;float3 lightDir = _WorldSpaceLightPos0 - i.posWS;UNITY_LIGHT_ATTENUATION(atten, i, i.posWS.xyz);half3 transLightDir = lightDir + nDirWS * _Distortion;float transDot = pow(max(0, dot(vDirWS, -transLightDir)), _Power) * _Scale;fixed3 transLight = (atten * 2) * (transDot + tex2D(_AOTex, i.uv0)) * tex2D(_Thickness, i.uv0).r * _SubColor.rgb;fixed3 transAlbedo = var_MainTex * _LightColor0.rgb * transLight;return float4(transAlbedo, 1.0);
}
ENDCG

天空盒同步Reflection Probes

        为了实现了为了实现视频中天空盒切换的效果,可以分为切换Skybox Material,以及切换场景中当前启用的Reflection Probe两部分。

        第一部分开始想的是只针对一个Material,把它设置为Skybox Material,更改它的_MainTex贴图,但貌似要开hdr贴图的read/write enable,还是选择了每个Hdr贴图配置一个Material,还可以分开调曝光。而在代码里直接给 RenderSettings.skybox赋值Material对象就行了。(Hdr来自HDRIs • Poly Haven)

        第二部分对每一个Skybox要进行一下Reflection Probe的烘焙,这里有个坑,注意一下Reflection Probe的类型,并不是多建几个Probes分别在不同天空盒下Bake一下就好了,经常会在启动后或者再烘焙别的什么Probe的时候,当前Probe的光照就变了。正确的做法是设置为Custom然后为其指定为已经烘焙好的Cubemap了,然后再启用不同的Probe就可以控制物体的反射。

后处理 Post Processing

        最后再简单的使用PostProcessing stack v2处理一下大概的效果如下,在运行中更改天空盒。

参考

  • 故宫文物虚拟仿真展示 unity制作与渲染 非HDRP(2016年制作) 3D扫描建模 玉石3S材质模拟 3D交互_哔哩哔哩_bilibili
  • 庄懂-BoyanTata的个人空间_哔哩哔哩_Bilibili
  • 一小时等于5年blender低模建模经验,不香吗?_哔哩哔哩_bilibili
  • HDRIs • Poly Haven
  • https://www.slideshare.net/colinbb/colin-barrebrisebois-gdc-2011-approximating-translucency-for-a-fast-cheap-and-convincing-subsurfacescattering-look-7170855

http://chatgpt.dhexx.cn/article/Tx3vRWlT.shtml

相关文章

Unity中的物体渲染顺序

big seven 文章目录 前言 一、摄像机渲染 二、划分渲染队列 三、不透明物体的渲染 四、透明物体的渲染 五、UGUI元素的渲染 总结 前言 Unity中物体的渲染顺序 提示:以下是本篇文章正文内容,下面案例可供参考 一、摄像机渲染 Unity中的渲染顺序首先是…

Unity渲染流程概述

本篇的任务是回答:在Untiy的渲染流程中CPU和GPU分别做了什么。 渲染到设备屏幕显示的每一帧的画面,都经历几个阶段的加工过程: 应用程序阶段(CPU):识别出潜在可视的网格实例,并把他们及其材质…

Unity_渲染_灯光_前向渲染

前向渲染路径 前向渲染的作用和意义场景内有多个灯光,如何渲染每个灯光对物体的影响 前向渲染的作用和意义 前向渲染的作用:处理多光源的渲染,多光源渲染在unity 有2中渲染方式 前向渲染和延时渲染 .延时渲染主要用于主机,PC平台,不在本次讨论范围.主要来研究前向渲染前向渲染…

【Unity渲染】前向渲染和延迟渲染的区别及切换

前向渲染和延迟渲染通道的区别,主要在对于光源的处理上。 Unity默认是前向渲染通道,如果光源特别多,可以使用延迟渲染。 前向渲染 使用前向渲染路径时,被照亮的对象将在单独的通道中进行渲染。根据场景中的光源数量以及它们是否…

从FrameDebugger看Unity渲染

从FrameDebugger看Unity渲染(一) Unity如何渲染一个3D2D的游戏画面,今天通过FrameDebugger来看下Unity内置渲染管线的渲染策略, 后续再出一些URP渲染管线相关的文章。 对啦!这里有个游戏开发交流小组里面聚集了一帮热爱学习游戏的零基础小白&#xff0c…

UnityShader入门精要——Unity中的渲染优化技术(二)

减少DrawCall数目 最常见的优化技术——批处理。实现原理为减少渲染每一帧所需的drawcall数目。使用同一个材质的物体可以一起处理。 优点缺点动态批处理切处理都是Unity 自动完成的,不需要我们自己做任何操作,而且物体是可以移动的限制很多&#xff0c…

Unity渲染顺序(2)

Camera 除了Screen Space - Overlay(屏幕空间覆盖模式)下的Canvas,场景中的其他物体需要渲染到屏幕中,都需要在指定的相机的绘制下。场景中可以创建多个相机,每个相机所拍摄的内容可能并不相同,在场景中有多相机的情况,不同的相机…

Unity渲染顺序(1)

添加排序层级 在Unity编辑器的右上角选择Layers 按钮,在下拉菜单中点击Edit Layers…选项,将显示当前Unity的Tags, Sorting Layers,和Layers 编辑选项。 Sorting Layers是Unity中对排序的层级的定义块,在面板中越靠后的排序层级越…

Unity的渲染流程

Unity中坐标空间的转换: Unity的渲染流程: 渲染到设备屏幕的每一帧画面都要经历如下几个阶段: 应用程序阶段(CPU):将材质和模型数据发送给GPU 几何阶段(GPU):进行顶点…

Unity 渲染原理

1 渲染流程 应用程序阶段(CPU):识别出潜在可视的网格实例,并把他们及其材质提交给 GPU 以供渲染。几何阶段(GPU):进行顶点变换等计算,并将三角形转换到齐次空间并进行裁剪。光栅化阶…

Unity标准化的场景渲染流程

笔者用的unity版本为2020.3.30f1c1,开一个HDRP模板场景,OK开始我们的操作。 第一步:删除场景中的所有东西只留下竹林玻璃房作为展示场景,将所有物体勾选Static,新增一个摄像机,如下图: 第二步&a…

Unity3D性能优化——渲染篇

大渣好,我又来了。 之前的文章中,我们了解了Profiler工具,以及在实际项目中unity的CPU优化分析及方法,本文我们主要了解在我们的项目中GPU的性能分析,以及对GPU性能进行优化的相关技术。 渲染优化 在了解优化渲染前&a…

Unity中的灯光和渲染

一:Unity中的灯光 ——Directional Light:模拟太阳光。它与位置无关,是平行光,可以调整旋转角度模拟昼夜 ——Spot Light:模拟车灯、手电筒的光、舞台灯光 ——Point Light:模拟灯泡 ——Area Light&#…

execv 函数的应用

execv函数族:系统来调用某程序模块 int execl(const char *path, const char *arg, ...); int execlp(const char *file, const char *arg, ...); int execle(const char *path, const char *arg, ..., char * const envp[]); int ex…

Linux 0.11-execve函数-35

Linux 0.11-execve函数-35 execve函数读取文件开头 1KB 的数据解析这 1KB 的数据为 exec 结构判断是脚本文件还是可执行文件准备参数空间设置 eip 和 esp,完成摇身一变累了吧,休息会 转载 execve函数 书接上回,上回书咱们说到,进…

Linux内核Hook系统调用execve

资源下载地址:linux内核hook系统调用execve函数-Linux文档类资源-CSDN下载 (已在内核为 4.19.0-amd64-desktop版本uos编译通过,并成功达到目的) 在Linux系统中,用户层程序无法直接控制系统内核,只能通过系…

执行新程序 execve()

新程序的执行 一:execve() 之所以叫新程序的执行,原因是这部分内容一般发生在fork()和vfork()之后,在子进程中通过系统调用execve()可以将新程序加载到子进程的内存空间。这个操作会丢弃原来的子进程execve()之后的部分,而子进程…

简单的execve流程

本文转载于网络 基于Linux0.11源码来叙述该功能,源码可以在oldlinux.org上自行获取 _sys_execve:lea EIP(%esp),%eax #取堆栈中存放系统调用的返回地址的地址pushl %eax #将该地址入栈call _do_execve #调用do_execve函数addl $4,%esp #丢弃该地址ret这边做了一个很…

Linux0.11系统调用之execve流程解析

Linux0.11系统调用之execve流程解析 前言execve功能介绍execve本质execve系统调用流程总结 前言 本文是基于Linux0.11源码来叙述该功能,源码可以在oldlinux.org上自行获取。 execve功能介绍 execve是用于运行用户程序(a.out)或shell脚本的…

5.execve()到底干了啥?

导语 很多童鞋有分析阅读Linux源代码的强烈愿望,可是Linux内核代码量庞大,大部分人不知道如何下手,以下是我分析Linux源代码的一些经验,仅供参考,有不实之处请大神指正! 1.要想阅读内核首先要进入内核&…