|
一、目的
解决substance painter制作好的模型贴图导入到unity效果不一致的问题,不能所见即所得,影响美术工作效率。保证Dcc软件和Unity的效果对齐是完善美术工业制作流程中不可或缺的一环。
二、设置同步
1. 在SubstancePainter和Unity内选用相同的光照环境(Enivronment Map)的HDRI图。Enviroment Opacity调成100,完全显示.Environment Blur改成0,不要模糊.方便观察周围环境。
着色器默认使用的是pbr-metal-rough。
导出相关贴图,选择输出模板,这里我的模板多加了ao通道贴图。
这里我的模板多加了ao通道贴图,设置如下。
得到贴图如下:
2.Unity使用相同的环境球。
光照设置如下,可暂时关闭场景中的直射光。
贴图设置,除Albedo外,其他贴图取消勾选sRGB。
材质球的设置,将贴图放入对应通道即可。
3.sp和Unity效果对比,可以发现sp的效果相比Unity暗部较暗。
三、渲染同步
sp默认的shader都放在Adobe Substance 3D Painter\resources\starter_assets\shaders目录下,参考glsl的编写结构,就可以重新自定义shader(注:需要实时刷新shader,不能放在默认目录下,选择导入文件,右键reload即可[1])。
sp自定义shader可参考:
使用sp的pbr输出局部光照和unity的对比:
Indirect Diffuse:基本相同
Indirect Specular:Unity的环境高光菲涅尔更加强烈
差异分析:
环境光照计算方式不同:1.在引擎里,我们通常使用directional light作为主光源(忽略点光,聚光灯等)进行直接光照的计算,使用solid color/skybox/gradient生成球谐参数,计算indirect diffuse,使用cubemap计算indirect specular。2.sp通过重要性采样来计算specular(具体算法参看Real Shading in Unreal Engine 4)。参考链接:
根据Unity的环境光照计算实现重写GlossyEnvironmentReflection函数。
half3 GlossyEnvironmentReflection(half3 reflectVector, half perceptualRoughness, half occlusion)
{
#if !defined(_ENVIRONMENTREFLECTIONS_OFF)
half mip = PerceptualRoughnessToMipmapLevel(perceptualRoughness);
// half4 encodedIrradiance = SAMPLE_TEXTURECUBE_LOD(unity_SpecCube0, samplerunity_SpecCube0, reflectVector, mip);
half3 encodedIrradiance = envSampleLOD(reflectVector, mip);
// #if defined(UNITY_USE_NATIVE_HDR)
half3 irradiance = encodedIrradiance.rgb;
// #else
// half3 irradiance = DecodeHDREnvironment(encodedIrradiance, unity_SpecCube0_HDR);
// #endif
return irradiance * occlusion;
#endif // GLOSSY_REFLECTIONS
half3 _GlossyEnvironmentColor = half3( 1,1,1); // !!TEMP
return _GlossyEnvironmentColor.rgb * occlusion;
}再次对比可以看到在采用环境球相同LOD时,sp和unity在相同级别下的值无法相对应,其中sp的lod级别存在10级,unity有7级。下图为lod级别都为4:
此处对Mip进行重映射的近似模拟计算[2]。
#define UNITY_SPECCUBE_LOD_STEPS 6
real PerceptualRoughnessToMipmapLevel(real perceptualRoughness, uint mipMapCount)
{
perceptualRoughness = perceptualRoughness * (1.7 - 0.7 * perceptualRoughness);
half mip = pow( perceptualRoughness, 0.4 );
//mip = pow( mip, 0.3 );
//mip *= 0.97;
//float unity_environment_lod_count = float(unity_specularprobe_lod_count);
#if 0
const float mipmap_end = environment_max_lod - environment_mipmap_bias;
const float mipmap_start = mipmap_end - UNITY_SPECCUBE_LOD_STEPS;
#elif 0
const float mipmap_start = max( 0, environment_max_lod - unity_environment_lod_count );
const float mipmap_end = min( unity_environment_lod_count, mipmap_start + UNITY_SPECCUBE_LOD_STEPS );
#elif 0
const float mipmap_start = 0;
const float mipmap_scale = environment_max_lod / unity_environment_lod_count;
const float mipmap_tail = ( unity_environment_lod_count - UNITY_SPECCUBE_LOD_STEPS ) * mipmap_scale - 1;
const float mipmap_end = min( environment_max_lod, environment_max_lod - mipmap_tail*1.2 );
#elif 1
const float mipmap_start = 0;
const float mipmap_end = environment_max_lod - 1.5;
#endif
return mip * ( mipmap_end - mipmap_start ) + mipmap_start;
// return perceptualRoughness * mipMapCount;
}对比:
BackGI:基本相同
AO:sp的AO多乘了阴影,sp有对应选项可以取消阴影。
去除阴影之后(为与Unity效果相一致默认关闭)。
再回到原始的pbr上,可以看到两边的效果基本一致。
添加直射光。在sp中利用shader定义主灯,并还原LightingPhysicallyBased的函数计算。
// get light
Light mainLight = GetMainLight();
mainLight.attenuation = getShadowFactor();
LocalVectors vectors = computeLocalFrame(inputs);
#ifdef _SPECULARHIGHLIGHTS_OFF
bool specularHighlightsOff = true;
#else
bool specularHighlightsOff = false;
#endif
BRDFData brdfData;
float smoothness = 1.0 - roughness;
InitializeBRDFData(baseColor,metallic,smoothness, brdfData);
vec3 lightbased=LightingPhysicallyBased(brdfData,mainLight,vectors.normal,vectors.eye,specularHighlightsOff);直接光还原对比:
四、最终效果
PS:对于自定义的shader可以自己根据glsl的语言进行shader转换。
参考
- ^https://zhuanlan.zhihu.com/p/370581942
- ^https://nagnae.wordpress.com/2018/08/05/substance-painters-shader-for-unity-%E4%B8%AD%E6%96%87/
|
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
×
|