|
URP
- SRP:可编程渲染管线,使其拥有更高扩展性,Unity2018.1版本推出了可编程渲染管线功能,并提供两个可以直接使用的SRP模板:HDRP\LWRP
- HDRP:为高端显卡的设备使用的渲染管线(ps5\XboxOne)\\ \\LWRP:为移动端渲染管线
- URP:在Unity2019.3版本讲LWRP进行升级,改名为URP
一.创建URP项目
二.升级URP项目
1.安装UPR扩展包
- Package Manager Unity Registry UniversalRp Install
2.创建UPR Asset
- 右击Assets Create Rendering UPRAssets(with UR)
项目当前路径下自动创建以上资源
- Unity在URP中开放出很多调整渲染质量的设置选项
渲染质量设置和在图形设置中添加URPAssets
3.升级旧材质
- 使用新的URPAsset之后,旧的Shader和URP不兼容,导致物体变为紫色,可以调整材质球
- Eidt Rendering Material Convert Select Build-in Material to URP
- Window Rendering Render Pipeline Converter
经过以上旧项目升级为URP项目
三.URP内置Shader
- Urp项目中,由于SRP管线不兼容旧的渲染管线,如果继续使用旧的Shader会报错,因此要使用URP -Shader
Shader存放路径
1.Lit-shader
- 此shader是基于物理渲染(PBR)光照模型,将Metallic和Specular工作流整合在一起
Lit-Shader材质面板
2.Simple Lit-Shader
移动端设备上运行,光照模型使用Blinn-Phong
3.Bake Lit-Shader
- 当需要风格化渲染,不需要实时光照\高光反射等渲染时,可以使用此shader,没有PBR\BlinnPhong光照,所有的光照数据来自Unity烘培的光照贴图和光照探灯,不支持实时光
4.Unit-Shader
Unit
四.Packages文件
文本样式为Shader的包含文件
- CoreRP Library \ Universal RP 文件
1.CoreRP Library ShaderLibrary,存放着Unity宏定义,预定义函数,不同平台的API等,真实名字为com.untiy.render-pipeline.core
- Common.hlsl:注意事项以及定义数据类型和一些通用性函数LinearEyeDepth( )函数
- CommonLighting.hlsl:定义了灯光计算的通用函数
- CommonMaterial.hlsl:粗糙度计算函数和纹理混合插值计算
- EntityLighting.hlsl:光照贴图采样和环境光解码
- Macros.hlsl:宏定义
- Packing.hlsl:数据解码
2.Universal RP ShaderLibrarty,存放着着URP内置的shader所关联的包含文件
- Core.hlsl:定义了一些数据结构
- Input.hlsl:定义了InputData结构体,变换矩阵宏定义
- lighting.hlsl:光照计算相关函数
- shadow.hlsl:计算阴影相关函数
- surfaceInput.hlsl:几种纹理采样函数[sNormal][AlbedoAlpha]
- UnityInPut..hlsl:包含了全局变量和变换矩阵
- BRDF.hlsl:BRDF结构体以及初始化
Lit.shader
- 此文件所在路径为:package/UniversalRP/Shaders/Lit.shader
一:Properties
属性
- 默认Unity将_MainTex的纹理属性为主纹理,如果想用不同的变量名可以使用指令[MainTexture]/[MainColor],如果添加多个指令,只对第一个有效
- 设置主纹理和主颜色后可以通过脚本传递参数给使用该shader材质球
- [ToggleOff]指令:数值类型的属性在材质面板显示为开关,如果属性设置了,还需要在编译指令中声明,[Toggle]指令:关键字后面为ON
二:SubShader
Subshader注释
- 渲染管线标签是必需的, 如果在Graphics中没有设置URP,这个Subshader将会失效。 可以添加一个subshader\fallBack-Build_in,让材质在URP管线和Build-in兼容
FallBack和自定义的ShaderGUI
UniversalRP-FallbackError.shader
Subshader中的pass个数
①ForwardLit Pass
- Tags{"LightMode" = "UniversalForward"}这个光照模式要与UniversalRenderPipeline.cs文件定义的名字像匹配,如果使用Unlit-shader可以不用"LightMode"
- 使用HLSL语言,之前的Cg语言会隐式包含了一些文件eg.“HLSLSupport.cginc”
编译指令
- 不为一些渲染平台编译Shader
- 不同的设备支持的 target shader model 是不一样
#pragma exclude_renderers gles gles3 glcore
#pragma target 4.5Pass中根据用途将Keywords分为3类
1.Material Keywords(材质属性):为材质面板上与属性对应
- 当添加了法线贴图,就会传入_NORMALMAP
- 当开启透明裁剪,就会传入_ALPHATEST_ON
2.Universal Pipeline keywords(渲染管线)为渲染管线声明与属性的对应
当开启主光投射阴影,就会传入 _MAIN_LIGHT_SHADOWS
3.Unity defined keywords(自定义)
- 这里主要在Lighting设置面板,是否使用光照贴图等
#pragma multi_compile _ LIGHTMAP_SHADOW_MIXING
#pragma multi_compile _ SHADOWS_SHADOWMASK
#pragma multi_compile _ DIRLIGHTMAP_COMBINED
#pragma multi_compile _ LIGHTMAP_ON
#pragma multi_compile _ DYNAMICLIGHTMAP_ON
#pragma multi_compile_fragment _ _GBUFFER_NORMALS_OCT
#pragma multi_compile_instancing
#pragma instancing_options renderinglayer
#pragma multi_compile _ DOTS_INSTANCING_ON
第一个pass结束,并未见到任何关于顶点/片段函数,代码包含在以下2个文件中
#inclue的定义方式
#ifndef UNIVERSAL_PIPELINE_CORE_INCLUDED
#define UNIVERSAL_PIPELINE_CORE_INCLUDED
...//文件代码
#endif
- #ifndef指令判断当前文件是否已经定义UNIVERSAL_PIPELINE_CORE_INCLUDED,如果没有被定义,那么就使用#define进行定义
包含文件.hlsl的使用方式
与主文件同路径
- #include"LitInput.hlsl"
- #include"./LitInput.hlsl" \\\\“./“表示返回主文件的父级
2.与主文件不同路径
- #include"Assets/ShaderInclude/UnlitInclude.hlsl"使用绝对路径
- 也可以使用相对路径,通过右击copy Path可以快速复制路径
LitInput.hlsl
- Litshader 第一个passForwadLit包含的第一个库文件, 主要是做了表面特征的的初始化
- 路径:Packages/com.unity.render-pipelines.universal/Shaders/LitInput.hlsl
一:声明属性变量
- URP中声明纹理资源的方式与传统的渲染流水线有些不同
//将声明的属性变量包含其中
//NOTE: Do not ifdef the properties here as SRP batcher can not handle different layouts.
CBUFFER_START(UnityPerMaterial)
float4 _BaseMap_ST;
...
half _Surface;
CBUFFER_END
- DX9之前不存在Cbuffer,顶点/片段函数访问同一个常量,必须设置两次,现在GPU单独划分出一块内存存储常量,所以不需要存储多次,可以高效进行计算
- URP纹理的声明方式与传统渲染流水线区别,unity将纹理声明和定义采样器分开
- 使用TEXTURE2D(_textureName):声明纹理!!!SAMPLER(sampler_textureName):定义纹理采样器!!
如果用到Scale和Offset,需要在Cbuffer中声明变量: 纹理名_ST
//Packages/com.unity.render-pipelines.universal/ShaderLibrary/SurfaceInput.hlsl
//_BaseMap/ _Bumpmap /_EmissionMap 在SurfaceInput.hlsl设置了
TEXTURE2D(_ParallaxMap); SAMPLER(sampler_ParallaxMap);
TEXTURE2D(_OcclusionMap); SAMPLER(sampler_OcclusionMap);
... ...
TEXTURE2D(_SpecGlossMap); SAMPLER(sampler_SpecGlossMap);
采样器:可以定义纹理设置面板上的Wrap Mode(重复模式)/Filter Mode(过滤模式)
采样器定义3种方式
- SAMPLER(sampler,_textureName):使用_textureName这个纹理在设置面板中设定采样方式
- 自定义采样器设置SAMPLER(filter_wrap)
3.SAMPLER(filter_wrapU_wrapV):可以为U和V设定不同的重复模式
二:纹理采样
//开启Specular工作流,采样的是_SpecGlossMap 贴图,否则对_MetallicGlossMap采样
#ifdef _SPECULAR_SETUP
#define SAMPLE_METALLICSPECULAR(uv) SAMPLE_TEXTURE2D(_SpecGlossMap, sampler_SpecGlossMap, uv)
#else
#define SAMPLE_METALLICSPECULAR(uv) SAMPLE_TEXTURE2D(_MetallicGlossMap, sampler_MetallicGlossMap, uv)
#endif
定义了宏在不同工作流所进行的操作
- URP中,纹理使用宏定义SAMPLE_TEXTURE2D(_textureName,sampler,uv)进行采样
Metallic和Specular采样函数
//传入参数纹理坐标/Albedo A通道
half4 SampleMetallicSpecGloss(float2 uv, half albedoAlpha)
{
half4 specGloss;
//有无Metallic\\Specular图
//有:采样
#ifdef _METALLICSPECGLOSSMAP
specGloss = half4(SAMPLE_METALLICSPECULAR(uv));
//Source = Albedo Alpha 吗?是:执行
#ifdef _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
specGloss.a = albedoAlpha * _Smoothness;
#else
specGloss.a *= _Smoothness;
#endif
//没有:不采样
#else // _METALLICSPECGLOSSMAP
#if _SPECULAR_SETUP
specGloss.rgb = _SpecColor.rgb;
#else
specGloss.rgb = _Metallic.rrr;
#endif
#ifdef _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
specGloss.a = albedoAlpha * _Smoothness;
#else
specGloss.a = _Smoothness;
#endif
#endif
AO图采样函数
half SampleOcclusion(float2 uv)
{
#ifdef _OCCLUSIONMAP
// TODO: Controls things like these by exposing SHADER_QUALITY levels (low, medium, high)
//目标平台移动设备
#if defined(SHADER_API_GLES)
return SAMPLE_TEXTURE2D(_OcclusionMap, sampler_OcclusionMap, uv).g;
#else
half occ = SAMPLE_TEXTURE2D(_OcclusionMap, sampler_OcclusionMap, uv).g;
return LerpWhiteTo(occ, _OcclusionStrength);
//路径:Packages/com.unity.render-pipelines.core/ShaderLibrary/CommonMaterial.hlsl
#endif
#else
return half(1.0);
#endif
}
SurfaceData结构体
struct SurfaceData
{
half3 albedo;
half3 specular;
half metallic;
half smoothness;
half3 normalTS;
half3 emission;
half occlusion;
half alpha;
half clearCoatMask;
half clearCoatSmoothness;
};
Alpha()函数
half Alpha(half albedoAlpha, half4 color, half cutoff)
{
#if !defined(_SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A) && !defined(_GLOSSINESS_FROM_BASE_ALPHA)
half alpha = albedoAlpha * color.a;
#else
half alpha = color.a;
#endif
#if defined(_ALPHATEST_ON)
clip(alpha - cutoff);
#endif
return alpha;
}
Albedo纹理采样函数
half4 SampleAlbedoAlpha(float2 uv, TEXTURE2D_PARAM(albedoAlphaMap, sampler_albedoAlphaMap))
{
return half4(SAMPLE_TEXTURE2D(albedoAlphaMap, sampler_albedoAlphaMap, uv));
}
法线贴图采样函数
half3 SampleNormal(float2 uv, TEXTURE2D_PARAM(bumpMap, sampler_bumpMap), half scale = half(1.0))
{
//判断是否有法线贴图传入
#ifdef _NORMALMAP
half4 n = SAMPLE_TEXTURE2D(bumpMap, sampler_bumpMap, uv);
//判断设备是否支持法线强度调整
#if BUMP_SCALE_NOT_SUPPORTED
return UnpackNormal(n);
#else
//Packages/com.unity.render-pipelines.core/ShaderLibrary/Packing.hlsl
//解码法线
return UnpackNormalScale(n, scale);
#endif
#else
return half3(0.0h, 0.0h, 1.0h);
#endif
}
表面数据初始化函数
//主要是为了初始化SurfaceData结构体
inline void InitializeStandardLitSurfaceData(float2 uv, out SurfaceData outSurfaceData)
{
//在D3D11中定义了将2个参数合并
//Packages/com.unity.render-pipelines.core/ShaderLibrary/API/D3D11.hlsl
//#define TEXTURE2D_ARGS(textureName, samplerName) textureName, samplerName
half4 albedoAlpha = SampleAlbedoAlpha(uv, TEXTURE2D_ARGS(_BaseMap, sampler_BaseMap));
outSurfaceData.alpha = Alpha(albedoAlpha.a, _BaseColor, _Cutoff);
half4 specGloss = SampleMetallicSpecGloss(uv, albedoAlpha.a);
outSurfaceData.albedo = albedoAlpha.rgb * _BaseColor.rgb;
//高光工作流
#if _SPECULAR_SETUP
outSurfaceData.metallic = half(1.0);
outSurfaceData.specular = specGloss.rgb;
//金属工作流
#else
outSurfaceData.metallic = specGloss.r;
outSurfaceData.specular = half3(0.0, 0.0, 0.0);
#endif
outSurfaceData.smoothness = specGloss.a;
outSurfaceData.normalTS = SampleNormal(uv, TEXTURE2D_ARGS(_BumpMap, sampler_BumpMap), _BumpScale);
outSurfaceData.occlusion = SampleOcclusion(uv);
outSurfaceData.emission = SampleEmission(uv, _EmissionColor.rgb,
TEXTURE2D_ARGS(_EmissionMap, sampler_EmissionMap));
#if defined(_CLEARCOAT) || defined(_CLEARCOATMAP)
half2 clearCoat = SampleClearCoat(uv);
outSurfaceData.clearCoatMask = clearCoat.r;
outSurfaceData.clearCoatSmoothness = clearCoat.g;
#else
outSurfaceData.clearCoatMask = half(0.0);
outSurfaceData.clearCoatSmoothness = half(0.0);
#endif
#if defined(_DETAIL)
half detailMask = SAMPLE_TEXTURE2D(_DetailMask, sampler_DetailMask, uv).a;
float2 detailUv = uv * _DetailAlbedoMap_ST.xy + _DetailAlbedoMap_ST.zw;
outSurfaceData.albedo = ApplyDetailAlbedo(detailUv, outSurfaceData.albedo, detailMask);
outSurfaceData.normalTS = ApplyDetailNormal(detailUv, outSurfaceData.normalTS, detailMask);
#endif
} |
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
×
|