unity urp 实现丝绸渲染

这篇具有很好参考价值的文章主要介绍了unity urp 实现丝绸渲染。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

首先看一下实际上真实的效果
unity urp 实现丝绸渲染
再来一张
unity urp 实现丝绸渲染
这是专门去找的。
可以看到丝绸渲染使用了各向异性的GGX去实现,有点仿头发的感觉,接下来看一下怎么实现的。

首先,准备实现双向反射率分布函数(BRDF)的DVF项。
D项使用UE里面的各项异性GGX:

// [Burley 2012, "Physically-Based Shading at Disney"]
float D_GGXaniso(float ax, float ay, float NoH, float XoH, float YoH)
{
	float a2 = ax * ay;
	float3 V = float3(ay * XoH, ax * YoH, a2 * NoH);
	float S = dot(V, V);

	return(1.0f / PI) * a2 * Square(a2 / S);
}

V项使用配合D项的Vis_SmithJointAniso

// [Heitz 2014, "Understanding the Masking-Shadowing Function in Microfacet-Based BRDFs"]
float Vis_SmithJointAniso(float ax, float ay, float NoV, float NoL, float XoV, float XoL, float YoV, float YoL)
{
	float Vis_SmithV = NoL * length(float3(ax * XoV, ay * YoV, NoV));
	float Vis_SmithL = NoV * length(float3(ax * XoL, ay * YoL, NoL));
	return 0.5 * rcp(Vis_SmithV + Vis_SmithL);
}
这个函数里面的x就是tangent y就是bitangent 中间的o就是dot计算结果

F项使用UE里面的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;
}

使用DVF项实现双向反射率分布函数:

float3 SlikBRDF(float3 DiffuseColor, float3 SpecularColor, float Roughness, float Anisotropy,
float3 N, float3 T, float3 B, float3 V, float3 L, float3 LightColor, float Shadow)
{
	float Alpha = Roughness * Roughness;
	float a2 = Alpha * Alpha;
	// Anisotropic parameters: ax and ay are the Roughness along the tangent and bitangent
	// Kulla 2017, "Revisiting Physically Based Shading at Imageworks"
	float ax = max(Alpha * (1.0 + Anisotropy), 0.001f);
	float ay = max(Alpha * (1.0 - Anisotropy), 0.001f);
	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));

	float XoV = dot(T, V);
	float XoL = dot(T, L);
	float XoH = dot(T, H);
	float YoV = dot(B, V);
	float YoL = dot(B, L);
	float YoH = dot(B, H);

	float3 Radiance = NoL * LightColor * Shadow * PI;
	
	//直接光漫反射
	float3 DiffuseTerm = Diffuse_Lambert(DiffuseColor) * Radiance;

	//直接光镜面反射
	float D = D_GGXaniso(ax, ay, NoH, XoH, YoH);
	float Vis = Vis_SmithJointAniso(ax, ay, NoV, NoL, XoV, XoL, YoV, YoL);
	float3 F = F_Schlick_UE4(SpecularColor, VoH);
	float3 SpecularTerm = ((D * Vis) * F) * Radiance;

	return DiffuseTerm + SpecularTerm;
}

其它代码,我们可以直接魔改unity的urp内置的lit函数,用于获取相关的参数,这里就不再聊了。
那么,你会发现一个问题,因为GGXaniso 主要使用的是tangent和bitangent的朝向做高光的,我们平时做高光的时候都是使用法向的, 法向贴图不会影响这两个朝向啊,那么怎么办,这么办:

    //设置T和B也受法线贴图的影响
    half3 tangentTS = normalize(surfaceData.normalTS.x * half3(0, 0, 1) * _NormalAniso + half3(1, 0, 0));
    half3 T = TransformTangentToWorld(tangentTS, tangentToWorld);
    T = NormalizeNormalPerPixel(T);

    half3 bitangentTS = normalize(surfaceData.normalTS.y * half3(0, 0, 1) * _NormalAniso + half3(0, 1, 0));
    half3 B = TransformTangentToWorld(bitangentTS, tangentToWorld);
    B = NormalizeNormalPerPixel(B);

我们用法向的x轴的量去影响切线空间下的切线的向量值,然后再将其转换到世界空间即可。
直接光的函数运算如下:

float3 DirectLighting(float3 DiffuseColor, float3 SpecularColor, float Roughness, float3 WorldPos, float Anisotropy, 
	float3 N, float3 T, float3 B, float3 V, float4 shadowCoord, float4 shadowMask)
{
	//主光源
	half3 DirectLighting_MainLight = half3(0, 0, 0);
	{
		Light light = GetMainLight(shadowCoord, WorldPos, shadowMask);
		half3 L = light.direction;
		half3 LightColor = light.color;
		half Shadow = light.shadowAttenuation;
		DirectLighting_MainLight = SlikBRDF(DiffuseColor, SpecularColor, Roughness, Anisotropy, N, T, B, V, L, LightColor, Shadow);
	}
	//附加光源
	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;
			DirectLighting_AddLight += SlikBRDF(DiffuseColor, SpecularColor, Roughness, Anisotropy, N, T, B, V, L, LightColor, Shadow);
		}
	#endif

	return DirectLighting_MainLight + DirectLighting_AddLight;
}

计算主光源和附加光源,即可实现直接光的漫反射和镜面反射。
unity urp 实现丝绸渲染
这是-0.9的Anisotropy的效果
unity urp 实现丝绸渲染
这是Anisotropy的值为0.9的效果,当前的双向反射率分布函数,如果把Anisotropy设置为1或者-1,效果上表现会很差。

环境光

首先,如果在环境光镜面反射上面实现aniso的效果呢,这里有段代码:

	//根据设置的各项异性的强度,对法向进行扭曲,实现各项异性的环境高光
	float3 anisotropicDirection = Anisotropy >= 0.0 ? B : T;
	float3 anisotropicTangent = cross(anisotropicDirection, V);
	float3 anisotropicNormal = cross(anisotropicTangent, anisotropicDirection);
	float3 bentNormal = normalize(lerp(N, anisotropicNormal, abs(Anisotropy)));

用这个最终生成的bentNormal去替换之前的计算反射角度的N,就可以实现环境光镜面反射,效果是这样的:
unity urp 实现丝绸渲染
为了看效果,我故意把光滑度调高了。
间接光的实现函数:

float3 IndirectLighting(float3 DiffuseColor, float3 SpecularColor, float Roughness, float3 WorldPos, float Anisotropy, 
float3 N, float3 T, float3 B, 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;
	
	//根据设置的各项异性的强度,对法向进行扭曲,实现各项异性的环境高光
	float3 anisotropicDirection = Anisotropy >= 0.0 ? B : T;
	float3 anisotropicTangent = cross(anisotropicDirection, V);
	float3 anisotropicNormal = cross(anisotropicTangent, anisotropicDirection);
	float3 bentNormal = normalize(lerp(N, anisotropicNormal, abs(Anisotropy)));

	//IBL
	half3 R = reflect(-V, bentNormal);
	R = RotateDirection(R, EnvRotation);
	half3 SpeucularLD = GlossyEnvironmentReflection(R, WorldPos, Roughness, Occlusion);
	half3 SpecularDFG = EnvBRDFApprox(SpecularColor, Roughness, NoV);
	float SpecularOcclusion = GetSpecularOcclusion(NoV, Pow2(Roughness), Occlusion);
	float3 SpecularAO = AOMultiBounce(SpecularColor, SpecularOcclusion);
	float3 IndirectSpecular = SpeucularLD * SpecularDFG * SpecularAO;

	return IndirectDiffuse + IndirectSpecular;
}

整体的效果:
unity urp 实现丝绸渲染文章来源地址https://www.toymoban.com/news/detail-494918.html

到了这里,关于unity urp 实现丝绸渲染的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Unity URP渲染管线与内置渲染管线的性能差别

    首先,我们来了解一下Unity的内置渲染管线。内置渲染管线是Unity较早版本中使用的默认渲染管线,它使用的是传统的图形渲染技术。内置渲染管线提供了一系列的渲染功能,如阴影、反射、抗锯齿等。但是,由于其较为庞大且复杂的设计,它的性能相对较低。在高质量图形效

    2024年02月08日
    浏览(41)
  • Unity内置渲染管线升级URP教程

    URP全称为Universal Render Pipeline(通用渲染管线),可以提供更加灵活的渲染方案,通过添加Render Feature实现各种渲染效果。并且可以针对移动平台进行专门的优化,同时还提供了SRPBatcher提高渲染效率。Unity的一些工具,比如ShaderGraph,也是必须在URP管线下才可以使用,可以说许多方

    2024年02月16日
    浏览(56)
  • Unity——URP & HDRP 渲染模式学习笔记

    目录 HDRP和UPR是两种完全不同的渲染模式,不能混用,只能选择其中一种,最好在项目刚开始的时候就确定好。否则后期所有模型的材质都要改变非常麻烦。 修改渲染模式方法: HDRP, URP, BRP区别 备注 project settins: 1. graphics-Scriptable render pipeline settings 要修改,假如从hdrp改为

    2024年02月04日
    浏览(48)
  • [Unity/URP学习]风格化水体渲染(一)

    着色:水体颜色、水体反射、水体折射、岸边泡沫、水面于天空沿边线消除、水体焦散 动画处理:水体流动、顶点动画、水体交互、水体浮力 (实现顺序没有严格按照着色和动画处理的分类来实现) 要制作水体颜色,要考虑的内容如下: 风格化的水体渐变颜色、水体深浅区

    2024年02月13日
    浏览(57)
  • 张益唐:数学的浪漫 —— 人工智能的很多东西实际上就是一种最优化问题

    张益唐,美国加州大学圣塔芭芭拉分校数学系终身教授。张益唐的研究方向是数论。2013年4月17日,他在《数学年刊》发表 《质数间的有界间隔》 ,在 孪生素数猜想 这一数论重大难题上取得重要突破。2022年,张益唐表示,在本质上,他已经证明了朗道-西格尔零点猜想,引发

    2024年02月07日
    浏览(54)
  • unity build-in 渲染管线升级urp渲染 shader篇

            由于工作原因需要对项目进行升级,从build-in渲染管线升级到urp渲染管线,我自己对应的unity版本是2018.版本升级到2021.3.2版本,由于最近几年unity版本升级比较快,个体版本差异有所不同,如遇与版本不一致问题敬请谅解。以下是根据官网等系列网站整理的内容

    2023年04月16日
    浏览(59)
  • Unity Shader从内置渲染管线迁移到URP

    Unity 在URP中将shader更新为了HLSL语言,使用build-in shader 无法直接在URP中使用 这里讲一下关于shader的更新方法 参考 From Built-in to URP Tags 添加 \\\"RenderPipeline\\\" = \\\"UniversalPipeline\\\" CGPROGRAM ENDCG 改变为 HLSLPROGRAM ENDHLSL #include \\\"UnityCG.cginc\\\" 更改为 #include \\\"Packages/com.unity.render-pipelines.universal/Sh

    2024年02月05日
    浏览(47)
  • Unity URP延迟渲染流程简单分析(Deferred Rendering)

      大概两个月前的某个Unity项目里选择使用了URP延迟渲染管线(其实没必要,主要是因为自己想用一用、学一学,因为后续自己的项目中需要使用延迟渲染),但在写Shader实现物体表面着色时却一直有个疑惑:   延迟渲染应该是先一个Pass将信息存储在GBuffer中,然后再一

    2024年02月07日
    浏览(45)
  • vscode显示当前打开的文件夹中没有git存储库,但实际上有.git文件夹。

    问题描述:当前打开的文件夹中没有 git 存储库。但实际上有.git文件夹。 解决方案:https://github.com/microsoft/vscode/issues/139598 The only way to make it work is to use the Git: Show Git Output… command. 在vscode的查看–命令面板,输入show git,执行后即可正确出现git 仓库。 如果执行上述命令后,

    2024年02月11日
    浏览(74)
  • Java——它要求用户输入一个整数(实际上是一个字符串),然后计算该整数的平方值,并将结果输出。

    这是一个Java程序,它要求用户输入一个整数(实际上是一个字符串),然后计算该整数的平方值,并将结果输出。程序的基本流程如下: 首先,声明并初始化变量data和result,它们的初始值都为0。 然后,输出提示信息,要求用户输入一个整数。 接下来,使用BufferedReader类从

    2024年02月11日
    浏览(44)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包