• 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);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

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

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

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

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

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

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

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

    //实现双层的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;
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
  • 相关阅读:
    [Vue]路由守卫
    聊聊Go里面的闭包
    P1387 最大正方形-前缀和
    耐酸碱腐蚀PFA冷凝回流装置进口透明聚四氟材质PFA梨形漏斗特氟龙圆底烧瓶
    【owt】vs2022 + v141 : 查看WINDOWSSDKDIR
    第二课第一周大作业--构建和评估一个线性风险模型
    音视频学习笔记——设计模式
    Python基于Flask的高校舆情分析,舆情监控可视化系统
    Coursera自动驾驶1.1-1.2——自动驾驶基础和软硬件架构
    Vue2生命周期详解
  • 原文地址:https://blog.csdn.net/qq_30100043/article/details/127397035