unity urp 实现衣服上面片的效果

在看模特秀的时候,有时候身上会有那种布灵布灵的面片效果。下面两张是我在丝绸的时装秀里面截取的两张模糊图,凑合看一下吧。
在这里插入图片描述在这里插入图片描述
如果需要在渲染里面去实现这种效果,该如何实现呢。
当然用我上一篇说到的泰森多边形了
https://blog.csdn.net/qq_30100043/article/details/127386983

我们可以使用其进行noise扰动,实现面片分离的效果,然后再使用其的id的值转换成为法向,相同片的法向相同,但由于id不同,每个片生成的法向的朝向也不相同,然后用这个法向去做高光效果,你就会得到一个亮片一个亮片的效果。
在这里插入图片描述
就比如这种效果,心动了吗,那么,接下来进入实战。

首先,就是用voronoi生成法向。

//亮片
float2 idvoronoi = 0;
float2 uvvoronoi = 0;
voronoi(input.uv * _FlakesScale, _FlakesAngle, idvoronoi, uvvoronoi, 0);
half3 voronoiNormal = half3(idvoronoi * _FlakesRange, 1.0); //使用voronoi函数生成的id作为扰动法向的xy
half3 noiseNormalWS = TransformTangentToWorld(voronoiNormal, tangentToWorld); //转换到世界空间坐标系下面
noiseNormalWS = NormalizeNormalPerPixel(noiseNormalWS);

如果需要voronoi函数,去上一篇去拿即可。

我们还需要一个亮片的颜色,在这里,我们刚好可以使用voronoi生成的uv去随便拾取一张多颜色亮片,然后和一个颜色相乘,还可以控制强度,相乘的颜色如果为0,那么亮片将不显示。

half3 flakesBaseColor = _FlakesColor * SAMPLE_TEXTURE2D(_FlakesMap, sampler_FlakesMap, uvvoronoi).rgb;

接下来就是重头戏了,数据都完成了,需要生成亮片的函数了:

half3 flakesColor = FlakesSpecular(_FlakesRoughness1, _FlakesRoughness2, _FlakesRoughnessMix, flakesBaseColor, positionWS, noiseNormalWS, viewDirWS, shadowCoord, shadowMask);

这里用了两个粗糙度,然后进行混合出来的,给亮片增加了过渡的效果。计算出来的结果和最终颜色相加即可。

接下来,将函数的实现代码粘贴出来,就是主光源和附加光源进行亮片计算即可。

//实现双层的GGX,这个专门是亮片使用的,F项就不需要根据视角进行过渡的效果了
float3 DualSpecularGGXFlakes(float Lobe0Roughness, float Lobe1Roughness, float LobeMix, float3 SpecularColor, float NoH, float NoV, float NoL)
{
    
    
	float Lobe0Alpha2 = Pow4(Lobe0Roughness);
	float Lobe1Alpha2 = Pow4(Lobe1Roughness);
	float AverageAlpha2 = Pow4((Lobe0Roughness + Lobe1Roughness) * 0.5);

	// Generalized microfacet specular
	float D = lerp(D_GGX_UE4(Lobe0Alpha2, NoH), D_GGX_UE4(Lobe1Alpha2, NoH), 1.0 - LobeMix);
	float Vis = Vis_SmithJointApprox(AverageAlpha2, NoV, NoL);
	float3 F = SpecularColor;

	return(D * Vis) * F;
}

//亮片的实现函数
float3 FlakesSpecular(float Lobe0Roughness, float Lobe1Roughness, float LobeMix, float3 SpecularColor, float3 WorldPos,
float3 N, float3 V, float4 shadowCoord, float4 shadowMask)
{
    
    
	//主光源
	half3 DirectLighting_MainLight = half3(0, 0, 0);
	{
    
    
		Light mainLight = GetMainLight(shadowCoord, WorldPos, shadowMask);
		half3 L = mainLight.direction;
		half3 LightColor = mainLight.color;
		half Shadow = mainLight.shadowAttenuation;
		
		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));

		float3 Radiance = NoL * LightColor * Shadow * PI;
		DirectLighting_MainLight = DualSpecularGGXFlakes(Lobe0Roughness, Lobe1Roughness, LobeMix, SpecularColor, NoH, NoV, NoL) * Radiance;
	}
	//附加光源
	half3 DirectLighting_AddLight = half3(0, 0, 0);
	#ifdef _ADDITIONAL_LIGHTS
		uint pixelLightCount = GetAdditionalLightsCount();
		for (uint lightIndex = 0; lightIndex < pixelLightCount; ++lightIndex)
		{
    
    
			Light light = GetAdditionalLight(lightIndex, WorldPos, shadowMask);
			half3 L = light.direction;
			half3 LightColor = light.color;
			half Shadow = light.shadowAttenuation * light.distanceAttenuation;
			
			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));

			float3 Radiance = NoL * LightColor * Shadow * PI;
			DirectLighting_AddLight += DualSpecularGGXFlakes(Lobe0Roughness, Lobe1Roughness, LobeMix, SpecularColor, NoH, NoV, NoL) * Radiance;
		}
	#endif

	return DirectLighting_MainLight + DirectLighting_AddLight;

}

猜你喜欢

转载自blog.csdn.net/qq_30100043/article/details/127397035