首页 > 其他分享 >Unity URP Shader之高级光照技术之SH

Unity URP Shader之高级光照技术之SH

时间:2023-01-05 15:44:06浏览次数:55  
标签:normal float Shader custom Unity SH world dir float3

首先声明以下素材和shader代码都来自Kerry佬,我只做整理和学习之用,写此随笔是为了做个笔记方便以后查阅。

 

SH,英文全称Spherical Harmonics Lighting,即球谐光照,主要用来模拟漫反射。 

1. 如何计算SH

SH只需要提供一组Vector4数组,便能通过算法来计算出漫反射光,这种方法的好处是适用于没有光照探针的场景中。如计算方法如下:

 1             half3 CalcSH(float3 normal_dir, half4 custom_SHAr, half4 custom_SHAg, half4 custom_SHAb, half4 custom_SHBr, half4 custom_SHBg, half4 custom_SHBb, half4 custom_SHC)
 2             {
 3                 float4 normalForSH = float4(normal_dir, 1.0);
 4                 //SHEvalLinearL0L1
 5                 half3 x;
 6                 x.r = dot(custom_SHAr, normalForSH);
 7                 x.g = dot(custom_SHAg, normalForSH);
 8                 x.b = dot(custom_SHAb, normalForSH);
 9 
10                 //SHEvalLinearL2
11                 half3 x1, x2;
12                 // 4 of the quadratic (L2) polynomials
13                 half4 vB = normalForSH.xyzz * normalForSH.yzzx;
14                 x1.r = dot(custom_SHBr, vB);
15                 x1.g = dot(custom_SHBg, vB);
16                 x1.b = dot(custom_SHBb, vB);
17 
18                 // Final (5th) quadratic (L2) polynomial
19                 half vC = normalForSH.x*normalForSH.x - normalForSH.y*normalForSH.y;
20                 x2 = custom_SHC.rgb * vC;
21 
22                 float3 sh = max(float3(0.0, 0.0, 0.0), (x + x1 + x2));
23                 sh = pow(sh, 1.0 / 2.2);
24                 return sh;
25             }

这一组Vector4数组如下:

 

2. 光照探针

unity中提供了Light Probe,即光照探针,来提前把光照信息烘焙到探针球里,这样物体进入探针区域后,通过取出影响物体的所有探针球,来计算出SH光照。

这是一种比较节省性能的做法。shader中计算SH光照可调用方法 half3 SampleSH(half3 worldNormal);

 

shader如下:

  1 Shader "MyURP/Kerry/SH/URPLightProbe"
  2 {
  3     Properties
  4     {
  5         _Tint("Tint",Color) = (1,1,1,1)
  6         _Expose("Expose",Float) = 1.0
  7         _Rotate("Rotate",Range(0,360)) = 0
  8         _NormalMap("Normal Map",2D) = "bump"{}
  9         _NormalIntensity("Normal Intensity",Float) = 1.0
 10         _AOMap("AO Map",2D) = "white"{}
 11         _AOAdjust("AO Adjust",Range(0,1)) = 1
 12 
 13     }
 14     SubShader
 15     {
 16         Tags
 17         {
 18             "RenderType" = "Opaque"
 19             "RenderPipeline" = "UniversalPipeline"
 20         }
 21         LOD 100
 22 
 23         Pass
 24         {
 25             Tags
 26             {
 27                 "LightMode" = "UniversalForward"
 28             }
 29 
 30             HLSLPROGRAM
 31             #pragma vertex vert
 32             #pragma fragment frag
 33             #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
 34             #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
 35 
 36             struct appdata
 37             {
 38                 float4 vertex : POSITION;
 39                 float2 texcoord : TEXCOORD0;
 40                 float3 normal : NORMAL;
 41                 float4 tangent : TANGENT;
 42             };
 43 
 44             struct v2f
 45             {
 46                 float2 uv : TEXCOORD0;
 47                 float4 pos : SV_POSITION;
 48                 float3 normal_world : TEXCOORD1;
 49                 float3 pos_world : TEXCOORD2;
 50                 float3 tangent_world : TEXCOORD3;
 51                 float3 binormal_world : TEXCOORD4;
 52             };
 53 
 54             //sampler2D _MainTex;
 55             //float4 _MainTex_ST;
 56             TEXTURECUBE(_CubeMap); SAMPLER(sampler_CubeMap);
 57             float4 _CubeMap_HDR;
 58             float4 _Tint;
 59             float _Expose;
 60 
 61             TEXTURE2D(_NormalMap); SAMPLER(sampler_NormalMap);
 62             float4 _NormalMap_ST;
 63             float _NormalIntensity;
 64             TEXTURE2D(_AOMap); SAMPLER(sampler_AOMap);
 65             float _AOAdjust;
 66             float _Rotate;
 67             float _Roughness;
 68             TEXTURE2D(_RoughnessMap); SAMPLER(sampler_RoughnessMap);
 69             float _RoughnessContrast;
 70             float _RoughnessBrightness;
 71             float _RoughnessMin;
 72             float _RoughnessMax;
 73 
 74 
 75             float3 RotateAround(float degree, float3 target)
 76             {
 77                 float rad = degree * PI / 180;
 78                 float2x2 m_rotate = float2x2(cos(rad), -sin(rad),
 79                     sin(rad), cos(rad));
 80                 float2 dir_rotate = mul(m_rotate, target.xz);
 81                 target = float3(dir_rotate.x, target.y, dir_rotate.y);
 82                 return target;
 83             }
 84 
 85             inline float3 ACES_Tonemapping(float3 x)
 86             {
 87                 float a = 2.51f;
 88                 float b = 0.03f;
 89                 float c = 2.43f;
 90                 float d = 0.59f;
 91                 float e = 0.14f;
 92                 float3 encode_color = saturate((x*(a*x + b)) / (x*(c*x + d) + e));
 93                 return encode_color;
 94             };
 95 
 96             v2f vert (appdata v)
 97             {
 98                 v2f o;
 99                 o.pos = TransformObjectToHClip(v.vertex.xyz);
100                 o.uv = v.texcoord * _NormalMap_ST.xy + _NormalMap_ST.zw;
101                 o.pos_world = mul(unity_ObjectToWorld, v.vertex).xyz;
102                 o.normal_world = normalize(mul(float4(v.normal, 0.0), unity_WorldToObject).xyz);
103                 o.tangent_world = normalize(mul(unity_ObjectToWorld, float4(v.tangent.xyz, 0.0)).xyz);
104                 o.binormal_world = normalize(cross(o.normal_world, o.tangent_world)) * v.tangent.w;
105                 return o;
106             }
107             
108             half4 frag (v2f i) : SV_Target
109             {
110                 half3 normal_dir = normalize(i.normal_world);
111                 half3 normaldata = UnpackNormal(SAMPLE_TEXTURE2D(_NormalMap,sampler_NormalMap,i.uv));
112                 normaldata.xy = normaldata.xy* _NormalIntensity;
113                 half3 tangent_dir = normalize(i.tangent_world);
114                 half3 binormal_dir = normalize(i.binormal_world);
115                 normal_dir = normalize(tangent_dir * normaldata.x + binormal_dir * normaldata.y + normal_dir * normaldata.z);
116 
117                 half ao = SAMPLE_TEXTURE2D(_AOMap, sampler_AOMap, i.uv).r;
118                 ao = lerp(1.0,ao, _AOAdjust);
119 
120                 half3 env_color = SampleSH(normal_dir);
121                 half3 final_color = env_color * ao * _Tint.rgb * _Expose;
122                 
123                 return float4(final_color,1.0);
124             }
125             ENDHLSL
126         }
127     }
128     FallBack "Hidden/Universal Render Pipeline/FallbackError"
129 }

效果如下:

 

 

转载请注明出处:https://www.cnblogs.com/jietian331/p/17027769.html

标签:normal,float,Shader,custom,Unity,SH,world,dir,float3
From: https://www.cnblogs.com/jietian331/p/17027769.html

相关文章

  • Unity URP Shader之高级光照技术之IBL
    首先声明以下素材和shader代码都来自Kerry佬,我只做整理和学习之用,写此随笔是为了做个笔记方便以后查阅。 IBL,英文全称ImageBasedLighting,即基于图像的照明,是一种通过......
  • UGUI之Mask切割图像shader应用
    在我之前的一篇文章写到使用Mask切割图像的方法。具体链接​​http://www.manew.com/thread-93954-1-1.html​​正如一些朋友所说上面这种方法把图放大之后确实存在有边缘出......
  • 转 Git配置SSH
    Git配置SSHhttp://t.csdn.cn/TT8QC林家小猪已于2022-05-2511:43:46修改26915收藏43分类专栏:软件安装文章标签:gitssh数据仓库版权华为云开发者联盟该内容已......
  • unity3d异步加载场景
    ​​unity3d​​​​loading界面​​​​异步加载​​​​进度条​​根据宣雨松前辈的教程来做的,因为我用到的场景不是在游戏里的那种(本人做增强现实的,完全把unity拿来做应......
  • [unity3D插件]Unity界面插件NGUI核…
    本文转载于互联网,是一个比较经典帖子,特来分享:UICamera-可以添加到任何相机,包含事件系统.UICamera是每个UI的重要组成部分.它负责发送Camera中所有NGUI的活动.如果场景中......
  • 圣诞树拼图游戏unity制作
    2022年圣诞节到来啦,很高兴这次我们又能一起度过~一、前言提示:使用unity来制作一个拼图游戏,图片便是圣诞树。二、创意名圣诞树拼图游戏三、效果展示圣诞树拼图游戏最终效果。......
  • unity和VS2019联调问题解决
    以前使用VS2015和17的时候联调的时候是可以附加到unity进行联调的,今天用的2019发现不可以了。研究了一下是少装了一个插件。装上插件就解决了。过程如下:当前使用VS版本2019......
  • unity如何检测第一次打开APP
    一般软件或app都会在第一次有指引和提示功能,例如第一次打开一个app要出现指引,第二次及以后就不会出现了。这个功能在​​unity​​里如何实现呢?下面用实例讲一下我的方法。......
  • Unity小地图Minimap制作全面功能介绍篇
    本系列文章将讲述如何制作小地图。功能如下:  小地图的局部放大地图,缩小功能。小地图展开成为大地图,以及与大地图的互相切换  大地图的人物图标跟随角色旋转和移动 ......
  • Unity游戏副本地图点击图标移动功能
    本篇讲相同的功能即:点击地图中的一个位置,让图标瞬间移动到点击位置,同时3D场景中人物也可以抵达场景中对应的点击位置。如图:操作方法和之前一样:找到大地图的渲染的Rawimage。......