Substance Painter

您所在的位置:网站首页 substance导入材质 Substance Painter

Substance Painter

2023-04-08 23:27| 来源: 网络整理| 查看: 265

美术经常有这样的困扰,“为什么我在SP里的效果是这样的,进了Unity就变成那样了?”

对于美术生产来说,不能所见即所得,进引擎的最终效果靠猜,是非常不利于美术创作的。

另一方面,没有这样的一个与引擎内效果统一的生产环境,也不利于外包的工作。

所以引擎与生产环境效果的统一,是打通PBR Pipeline的重要一环,对工业化水平的提升是非常有意义的。

目前网上找到的分享中,大都有这样的困扰,就是由于Unity和SP两边光照环境的区别,很难做到非常一致的效果。

这里给大家分享一个Unity效果还原到SP的方法,通过将Unity的光照Shader还原到SP中,基本可以做到两边的效果比较相似。

光照环境

在SP的Shader中直接写入直接光照来统一两边表现可以比较简单的实现,这里按下不表,主要讲一下怎么把Unity的环境高光挪到SP里。

SP中是通过对环境进行重要性采样来计算IBL的,而Unity中是根据粗糙度来采样Cubemap,但是这个Cubemap是Unity提前Bake好的。

Studio 03 的mipmap,在Unity(上)与SP(下)中的对比

挖了下Unity源码,没有看到具体是怎么Bake的,所以使用了非常暴力的做法,直接把Unity烘焙好的环境球提供给SP,Shader直接采样这个Unity的Cubemap,不再采样SP自己的环境。通过这样的方式,来统一两边的环境光照。

Shader

Substance的API文档和自带的几个Shader都是很好的参考对象。

Shader相对比较直接,把Unity的算法搬过来就好,基本在以下几个地方:

Internal-DeferredReflectionsUnityPBSLightingUnityGlobalIlluminationUnityStandardBRDFUnityImageBasedLighting

可以先把half3这些define了,把常用函数也复制过来,抄起来方便很多,这点可以参考nagnae的这篇blog文章。另外这篇文章的最后也准备了懒人包。

因为是先写了原生Unity 5.6的效果再在那个的基础上还原自己项目的Shader,这里稍微分享下原生Unity SP Shader的片段。

间接高光部分。

half3 IndirectSpecular(LocalVectors vectors, half roughness, half occlusion) { roughness = roughness*(1.7 - 0.7*roughness); half mip = perceptualRoughnessToMipmapLevel(roughness); half3 reflUVW = reflect(-vectors.eye, vectors.normal); half3 env0 = envSampleLODCustom(reflUVW, mip).rgb; return env0 * occlusion; }写Shader的过程中可以通过对比一些中间结果确定自己没跑偏,上图显示的是mip

BRDF(连人家的注释都一起抄过来),这里只有高光。

half3 UNITY_BRDF_PBS(LocalVectors vectors, UnityStandardData data, float oneMinusReflectivity) { half perceptualRoughness = SmoothnessToPerceptualRoughness (data.smoothness); half roughness = PerceptualRoughnessToRoughness(perceptualRoughness); vec3 Ln = half3(0, 1, 0); vec3 Hn = normalize(Ln + vectors.eye); float nv = saturate(dot(data.normalWorld, vectors.eye)); float nl = saturate(dot(vectors.normal, Ln)); float nh = saturate(dot(vectors.normal, Hn)); float lv = saturate(dot(Ln, vectors.eye)); float lh = saturate(dot(Ln, Hn)); float vh = saturate(dot(vectors.eye, Hn)); half diffuseTerm = DisneyDiffuse(nv, nl, lh, perceptualRoughness) * nl; half V = SmithJointGGXVisibilityTerm (nl, nv, roughness); half D = GGXTerm (nh, roughness); half specularTerm = V * D * 3.14159265359; // Torrance-Sparrow model, Fresnel is applied later // specularTerm * nl can be NaN on Metal in some cases, use max() to make sure it's a sane value specularTerm = max(0, specularTerm * nl); // To provide true Lambert lighting, we need to be able to kill specular completely. specularTerm *= any(data.specularColor) ? 1.0 : 0.0; // surfaceReduction = Int D(NdotH) * NdotH * Id(NdotL>0) dH = 1/(roughness^2+1) float surfaceReduction = 1.0 / (roughness*roughness + 1.0); half grazingTerm = saturate(data.smoothness + (1 - oneMinusReflectivity)); return surfaceReduction * IndirectSpecular(vectors, perceptualRoughness, data.occlusion) * FresnelLerp(data.specularColor, vec3(grazingTerm), nv); }

结果

放一个原生Unity配Substance Painter的效果。

目测效果还是挺像的再放个原生pbr-metal-rough的效果写在最后的一些实用小东西

在SP里刷新Shader

SP的Custom Shader是不会实时更新效果的,如何在SP里刷新修改后的Shader呢?

首先在某个位置创建自己的glsl Shader;

然后将Shader文件拖进SP,在导入设置里选择project项;

导入Shader的时候,选择当前的project

修改了Shader文件,想要在SP中看到效果的时候,右键Shader选择Reload

修改Shader后,Reload

这个小技巧是参考了harayoki的分享,原文在这里。

Unity环境球转到Substance的一些细节

SP不认Cubemap,所以需要做一个转换。

SP不认Cubemap,需要转成Lat-Long格式

这个Staff推荐的HDRShop我只试了v1,不太好用。推荐使用ImageViewer这个工具,很方便。

懒人包

half Pow5 (half x) { return x*x * x*x * x; } half SpecularStrength(half3 specular) { return max (max (specular.r, specular.g), specular.b); } half perceptualRoughnessToMipmapLevel(half perceptualRoughness) { return perceptualRoughness * MIP_STEP; } half DisneyDiffuse(half NdotV, half NdotL, half LdotH, half perceptualRoughness) { half fd90 = 0.5 + 2 * LdotH * LdotH * perceptualRoughness; // Two schlick fresnel term half lightScatter = (1 + (fd90 - 1) * Pow5(1 - NdotL)); half viewScatter = (1 + (fd90 - 1) * Pow5(1 - NdotV)); return lightScatter * viewScatter; } half SmithJointGGXVisibilityTerm (half NdotL, half NdotV, half roughness) { half a = roughness; half lambdaV = NdotL * (NdotV * (1 - a) + a); half lambdaL = NdotV * (NdotL * (1 - a) + a); return 0.5f / (lambdaV + lambdaL + 1e-5f); } half GGXTerm (half NdotH, half roughness) { half a2 = roughness * roughness; half d = (NdotH * a2 - NdotH) * NdotH + 1.0f; // 2 mad return 0.31830988618 * a2 / (d * d + 1e-7f); // This function is not intended to be running on Mobile, // therefore epsilon is smaller than what can be represented by half } half3 FresnelLerp(half3 F0, half3 F90, half cosA) { half t = Pow5(1 - cosA); // ala Schlick interpoliation return lerp(F0, F90, t); } half3 DiffuseFromMetallic (half3 albedo, half metallic) { float oneMinusReflectivity = OneMinusReflectivityFromMetallic(metallic); return albedo * oneMinusReflectivity; } half3 SpecularFromMetallic (half3 albedo, half metallic) { return lerp (unity_ColorSpaceDielectricSpec.rgb, albedo, metallic); }参考Substance Docs,Shader API,2021Razor Yang,简单聊聊CODM的图形,2021harayoki,【SubstancePainter】編集中のシェーダーをすぐさまリロードする, 2019nagnae,Substance Painter's shader for Unity,2018月光下的旅行,Substance Painter Shader与UE4移动端渲染效果同步2020IanBanks, arma 3 substance shader, 2018



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3