unity urp 棉麻织物渲染

Posted 暮志未晚Webgl

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了unity urp 棉麻织物渲染相关的知识,希望对你有一定的参考价值。


我在前一篇写了对于衣服和硬表面材质的区别。这一篇来实现一下正常的棉麻类的渲染实现。
首先,说一下棉麻类的衣服的特点。
棉麻类的布料是由线组成的,也就是一根根的线织出来的,所以它是相对来说比较平整的结构。但是呢,它还有一层在表面绒毛的存在,这是一层的绒纤维,属于一层树立在表面的短绒毛,但是这层绒毛的方向和长短都是不确定的,在渲染时,我们需要考虑一下这层绒毛的效果。
所以,为了实现棉麻类的效果,我们需要实现这两层的渲染效果。
那么,在直接光渲染时,漫反射我们还是使用默认的漫反射,但是在实现直接光的镜面高光时,我们需要使用两层高光去实现。之前也说过,正常的表面使用反向的GGX高光,然后再使用一层高光来表现表层上面的绒毛的镜面高光效果。
在实现绒毛效果上,它是在边缘的比较发亮的,所以,我们需要一张lut图取获取第二层高光的强度。
代码如下:

float3 ClothBRDF(float3 DiffuseColor, float3 SheenColor, float Roughness, float SheenRoughness, float SheenDFG, float3 N, float3 V, float3 L, float3 LightColor, float Shadow)

	float a2 = Pow4(Roughness);
	float3 H = normalize(L + V);
	float NoH = saturate(dot(N, H));
	float NoV = saturate(abs(dot(N, V)) + 1e-5);
	float NoL = saturate(dot(N, L));
	float VoH = saturate(dot(V, H));
	float3 Radiance = NoL * LightColor * Shadow * PI;
	
	//默认的漫反射
	float3 DiffuseLighting = Diffuse_Lambert(DiffuseColor) * Radiance;
	
	//默认的brdf
	float D = D_Charlie_Filament(Roughness, NoH);
	float Vis = Vis_Cloth(NoV, NoL);
	float3 F = F_Schlick_UE4(0.04, VoH);
	float3 SpecularLighting = ((D * Vis) * F) * Radiance;

	//第二层绒毛类的brdf
	float D2 = D_Charlie_Filament(SheenRoughness, NoH);
	float Vis2 = Vis_Cloth(NoV, NoL);
	float3 F2 = SheenColor;
	float3 SheenLighting = ((D2 * Vis2) * F2) * Radiance;

	//能量守恒,求出第二层的强度,减少其它强度
	float sheenScaling = 1.0 - max(max(SheenColor.r, SheenColor.g), SheenColor.b) * SheenDFG;
	DiffuseLighting *= sheenScaling;
	SpecularLighting *= sheenScaling;

	float3 DirectLighting = DiffuseLighting + SpecularLighting + SheenLighting;
	return DirectLighting;


可以使用类似于上面的图,根据视角和法向作为u的值,然后以粗糙度作为v的值去获取当前第二层高光的强度。

//求出绒毛层的dfg (反射强度)
half2 dfgUV = half2(saturate(dot(normalWS, viewDirWS)), sfd.sheenRoughness);
half dfg = SAMPLE_TEXTURE2D(_DiffuseMap, sampler_DiffuseMap, dfgUV).r;


调的低一些,效果更明显

绒毛的效果是杂乱无章的,所以,我们需要一张贴图来表现出那种效果,还需要一张绒毛效果的图

//求出绒毛层的dfg (反射强度)
half2 dfgUV = half2(saturate(dot(normalWS, viewDirWS)), sfd.sheenRoughness);
half dfg = SAMPLE_TEXTURE2D(_ClothDGF_LUT, sampler_ClothDGF_LUT, dfgUV).r;
half2 fuzzUV = TRANSFORM_TEX(UV, _FuzzMap);
half fuzz = SAMPLE_TEXTURE2D(_FuzzMap, sampler_FuzzMap, fuzzUV).r;
dfg *= fuzz;


使用图片以后,会发现有那种杂乱无章的绒毛的效果了。

然后加一个颜色用于控制第二层的颜色效果。
能量守恒,高光的强度全体为1,所以我们需要在生产第二次高光时,做一下处理。

使用的dvf三项的代码,我也列出来

//Filament引擎的渲染衣服使用的D项
float D_Charlie_Filament(float Roughness, float NoH)

	// Estevez and Kulla 2017, "Production Friendly Microfacet Sheen BRDF"
	float invAlpha = 1.0 / Pow2(Roughness);
	float cos2h = NoH * NoH;
	float sin2h = max(1.0 - cos2h, 0.0078125); // 2^(-14/2), so sin2h^2 > 0 in fp16
	return(2.0 + invAlpha) * pow(sin2h, invAlpha * 0.5) / (2.0 * PI);

//衣服类brdf的v项
float Vis_Cloth(float NoV, float NoL)

	return saturate(1.0 / (4.0 * (NoL + NoV - NoL * NoV)));

//ue的pbr使用的f项
// [Schlick 1994, "An Inexpensive BRDF Model for Physically-Based Rendering"]
float3 F_Schlick_UE4(float3 SpecularColor, float VoH)

	float Fc = Pow5(1 - VoH);					// 1 sub, 3 mul
	//return Fc + (1 - Fc) * SpecularColor;		// 1 add, 3 mad
	
	// Anything less than 2% is physically impossible and is instead considered to be shadowing
	return saturate(50.0 * SpecularColor.g) * Fc + (1 - Fc) * SpecularColor;

接下来是间接光部分的处理
间接光漫反射还是使用球谐光照的方式去处理

//SH
float3 DiffuseAO = AOMultiBounce(DiffuseColor, Occlusion);
float3 RadianceSH = SampleSH(N);
float3 IndirectDiffuse = RadianceSH * DiffuseColor * DiffuseAO;
float3 AOMultiBounce(float3 BaseColor, float AO)

	float3 a = 2.0404 * BaseColor - 0.3324;
	float3 b = -4.7951 * BaseColor + 0.6417;
	float3 c = 2.7552 * BaseColor + 0.6903;
	return max(AO, ((AO * a + b) * AO + c) * AO);

在间接光镜面反射部分,使用到了双层处理的方案

float3 IndirectLighting(float3 DiffuseColor, float3 SheenColor, float Roughness, float SheenRoughness, float ClothDFG, float SheenDFG,
float3 WorldPos, float3 N, float3 V, float Occlusion, float EnvRotation)

	float NoV = saturate(abs(dot(N, V)) + 1e-5);
	//SH
	float3 DiffuseAO = AOMultiBounce(DiffuseColor, Occlusion);
	float3 RadianceSH = SampleSH(N);
	float3 IndirectDiffuse = RadianceSH * DiffuseColor * DiffuseAO;
	//IBL
	half3 R = reflect(-V, N);
	R = RotateDirection(R, EnvRotation);

	//获取第一层的镜面反射
	half3 SpeucularLD = GlossyEnvironmentReflection(R, WorldPos, Roughness, 1.0f); //在反射球上获取镜面反射颜色
	half3 SpecularDFG = ClothDFG * 0.04; //获取到衣服的反射强度 0.04是默认的非金属反射强度
	float SpecularOcclusion = GetSpecularOcclusion(NoV, Pow2(Roughness), Occlusion); //计算镜面反射的AO
	float3 SpecularAO = AOMultiBounce(float3(0.04, 0.04, 0.04), SpecularOcclusion); //AO和基础色进行混合
	float3 IndirectSpecular = SpeucularLD * SpecularDFG * SpecularAO;

	//获取绒毛层的镜面反射
	half3 SheenSpeucularLD = GlossyEnvironmentReflection(R, WorldPos, SheenRoughness, 1.0f);
	half3 SheenSpecularDFG = SheenColor * SheenDFG; //绒毛的反射强度
	float SheenOcclusion = GetSpecularOcclusion(NoV, Pow2(SheenRoughness), Occlusion); //计算镜面反射的AO
	float3 SheenAO = AOMultiBounce(SheenColor, SheenOcclusion); //AO和基础色进行混合
	float3 SheenSpecular = SheenSpeucularLD * SheenSpecularDFG * SheenAO;

	//能量守恒
	float sheenScaling = 1.0 - max(max(SheenColor.r, SheenColor.g), SheenColor.b) * SheenDFG;
	IndirectDiffuse *= sheenScaling;
	IndirectSpecular *= sheenScaling;

	return IndirectDiffuse + IndirectSpecular + SheenSpecular;

里面新增加的ClothDFG 是使用DFG_LUT贴图使用默认的roughness求得。

最终,就有了带有绒毛效果的棉麻织物的效果了。

以上是关于unity urp 棉麻织物渲染的主要内容,如果未能解决你的问题,请参考以下文章

unity urp 衣服渲染

unity urp 衣服渲染

unity urp 实现衣服绒毛效果

unity urp 实现衣服绒毛效果

Unity教程:URP渲染管线实战教程系列

unity渲染管线及升级URP