色调映射视差偏移

色调映射视差偏移

三月 26, 2022

Blinn-Phong

半角向量=观察方向V+光照方向L;

1
2
3
4
5
half3 view_dir = normalize(_WorldSpaceCameraPos.xyz - i.pos_world);
half3 light_dir =normalize( _WorldSpaceLightPos0.xyz );
half3 half_dir = normalize(view_dir+light_dir);
half NotH = max(dot(normal_dir,half_dir),0);
half3 specular = pow(max(NotH,0),_Shininess)* _LightColor0.xyz*_SpecularIntensity*spec_mask;

色彩映射

高光部分过曝,使得颜色直接变白色为了体现更多细节,将色调重新映射,注意一般这个处理都在后处理完成。实现如下。

1
2
3
4
5
6
7
8
9
10
11
12
float3 ACESFilm(float3 x)
{
float a = 2.51f;
float b = 0.03f;
float c = 2.43f;
float d = 0.59f;
float e = 0.14f;
return saturate((x*(a*x + b)) / (x*(c*x + d) + e));
};
base_color =pow(base_color,2.2);
half3 tone_color = ACESFilm(col.xyz);
col.xyz=pow(tone_color,1.0/2.2);

视察偏移

用高度图模拟侧面的观察的遮挡问题

1
2
3
4
5
6
7
8
9
10
11
float3 view_tangentspace = normalize(mul(TBN,view_dir));
half2 uv_parallax = i.uv;
for(int j=0;j<_HeightTime;j++)
{
half height = tex2D(_Parallax,uv_parallax);
uv_parallax = uv_parallax - (0.5 - height) * (view_tangentspace.xy/view_tangentspace.z+0.42) *_ParallaxIntensity*0.01f;
}
half3 base_color = tex2D(_MainTex, uv_parallax).xyz;
base_color =pow(base_color,2.2);
half3 AO = tex2D(_AOMap,uv_parallax).xyz;
half3 spec_mask = tex2D(_SpecMask,uv_parallax).xyz;

阴影

在这里插入图片描述

实时阴影

理论知识全适用,但代码只适用于内置渲染管线

传统实时阴影

在这里插入图片描述

阴影距离决定定向光的拍摄位置位置大概是

1
//摄像头的 forword 向量*阴影距离 向光照反方向 + 阴影距离

在光源位置做摄像机,拍摄一张深度图

在这里插入图片描述

将光源摄像头内的顶点转入光源相机空间用z坐标z1和shadowMap的灰度值z2进行比对,z1<z2,则不再阴影区,最佳理解:就是单纯的摄像机深度剔除的部分,把光源看作摄像机,看到的就被照亮,没看到的就是阴影咯。

Unity屏幕空间阴影

用摄像头view渲染深度图,渲染的深度图可以还原屏幕需要的片元的世界坐标空间进行优化

在这里插入图片描述

在这里插入图片描述

然后从Camera直接转到光照摄像头坐标系下。

联级阴影 CSM

以下是个人通过unity猜测出来的,暂未找资料

分成四个区域,越靠近物体联级越多,把所有得到的联级进行均值混合原理还是前两种方法

证明

无联级,阴影距离3.3

在这里插入图片描述

两联级,阴影距离10

在这里插入图片描述

得到的阴影效果会胡一点,可能是混合了

阴影相关的内置函数

只计算实时阴影

记得把v2f结构体中的vertex改成pos。

1
2
3
SHADOW_COORDS(5)
TRANSFER_SHADOW(o)
half shadow = SHADOW_ATTENUATION(i);

多光源

混合光源计算

1
2
3
4
LIGHTING_COORDS(5,6)
TRANSFER_VERTEX_TO_FRAGMENT(o);
half atten = LIGHT_ATTENUATION (i);
half NotL = min(atten,max(dot(normal_dir,light_dir),0));

在forwardadd中一定把环境光删除,否则出现阴影锯齿。

代码

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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
Shader "lit/Blin-Phong"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_NormalMap("Normal Map",2D)="bump"{}
_NormalIntensity("Normal Intensity",Range(0.0,5.0))= 1.0
_AOMap("AO Map",2D)="white"{}
_SpecMask("Spec Mask",2D)="white"{}
_Shininess ("Shininess", Float) = 1
_SpecularIntensity("SpecularIntensity",Range(0.01,5))= 1.0
_Parallax("Parallax",2D)="black"{}
_ParallaxIntensity("Parallax Intensity",Float)=1.0

_HeightTime("Height Time",Range(0,10))=1.0
//_AmbientColor("Ambient Color",Color)=(0,0,0,0)
// __AmbientIntensity("Ambient Intensity",Float)=0



}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100

Pass
{
Tags { "LightMode" = "ForwardBase"}

CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_fwdbase
#include "UnityCG.cginc"
#include "AutoLight.cginc"

struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
float3 normal:NORMAL;
float4 tangent:TANGENT;
};

struct v2f
{
float2 uv : TEXCOORD0;
float4 pos : SV_POSITION;
float3 normali_dir:TEXCOORD1;
float3 tangent_dir:TEXCOORD2;
float3 binormal_dir:TEXCOORD3;
float3 pos_world:TEXCOORD4;
SHADOW_COORDS(5)
};

sampler2D _MainTex;
float4 _MainTex_ST;
sampler2D _AOMap;
float4 _AOMap_ST;
float4 _LightColor0;
float _Shininess;
float _SpecularIntensity;
//float4 _AmbientColor;
sampler2D _SpecMask;
float _SpecMask_ST;
sampler2D _NormalMap;
float4 _NormalMap_ST;
float _NormalIntensity;
sampler2D _Parallax;
float _ParallaxIntensity;
float _HeightTime;
//float __AmbientIntensity;

float3 ACESFilm(float3 x)
{
float a = 2.51f;
float b = 0.03f;
float c = 2.43f;
float d = 0.59f;
float e = 0.14f;
return saturate((x*(a*x + b)) / (x*(c*x + d) + e));
};

v2f vert (appdata v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.normali_dir = normalize(mul(float4(v.normal,0.0),unity_WorldToObject).xyz);
o.tangent_dir = normalize(mul(float4(v.tangent.xyz,0.0),unity_WorldToObject).xyz);
o.binormal_dir = normalize(cross(o.normali_dir,o.tangent_dir))* v.tangent.w;
o.pos_world = mul(unity_ObjectToWorld,v.vertex).xyz;
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
TRANSFER_SHADOW(o)
return o;
}

fixed4 frag (v2f i) : SV_Target
{
fixed4 col=fixed4(0,0,0,0);


half shadow = SHADOW_ATTENUATION(i);
half4 normalmap = tex2D(_NormalMap,i.uv);
half3 view_dir = normalize(_WorldSpaceCameraPos.xyz - i.pos_world);
half3 light_dir =normalize( _WorldSpaceLightPos0.xyz );
half3 half_dir = normalize(view_dir+light_dir);
//Normal
half3 normal_dir =normalize(i.normali_dir);
half3 tangent_dir =normalize(i.tangent_dir)*_NormalIntensity;
half3 binormal_dir =normalize(i.binormal_dir)*_NormalIntensity;
half3 normal_data = UnpackNormal(normalmap);
float3x3 TBN = float3x3(tangent_dir,binormal_dir,normal_dir);
normal_dir =normalize(mul(normal_data,TBN));
//normal_dir=tangent_dir*normal_data.x*_NormalIntensity+binormal_dir*normal_data.y*_NormalIntensity+normal_dir*normal_data.z ;

float3 view_tangentspace = normalize(mul(TBN,view_dir));
half2 uv_parallax = i.uv;
for(int j=0;j<_HeightTime;j++)
{
half height = tex2D(_Parallax,uv_parallax);
uv_parallax = uv_parallax - (0.5 - height) * (view_tangentspace.xy/view_tangentspace.z+0.42) *_ParallaxIntensity*0.01f;
}
half3 base_color = tex2D(_MainTex, uv_parallax).xyz;
base_color =pow(base_color,2.2);
half3 AO = tex2D(_AOMap,uv_parallax).xyz;
half3 spec_mask = tex2D(_SpecMask,uv_parallax).xyz;


half NotL = min(shadow,max(dot(normal_dir,light_dir),0));
half NotH = max(dot(normal_dir,half_dir),0);
half3 diffuse = NotL*_LightColor0.xyz;
half3 specular = pow(max(NotH,0),_Shininess)* _LightColor0.xyz*_SpecularIntensity*spec_mask*NotL;
// half3 ambient = _AmbientColor.xyz*__AmbientIntensity;

//col.xyz+= AO;

col.xyz += diffuse;
col.xyz += specular;
col.xyz += UNITY_LIGHTMODEL_AMBIENT.xyz;

// sample the texture
col.xyz *=base_color;
col.xyz *=AO;
half3 tone_color = ACESFilm(col.xyz);
col.xyz=pow(tone_color,1.0/2.2);
// apply fog
return col;
}
ENDCG
}
Pass
{
Tags { "LightMode" = "ForwardAdd"}
Blend One One
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_fwdadd
#include "UnityCG.cginc"
#include "AutoLight.cginc"

struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
float3 normal:NORMAL;
float4 tangent:TANGENT;
};

struct v2f
{
float2 uv : TEXCOORD0;
float4 pos : SV_POSITION;
float3 normali_dir:TEXCOORD1;
float3 tangent_dir:TEXCOORD2;
float3 binormal_dir:TEXCOORD3;
float3 pos_world:TEXCOORD4;
LIGHTING_COORDS(5,6)
};

sampler2D _MainTex;
float4 _MainTex_ST;
sampler2D _AOMap;
float4 _AOMap_ST;
float4 _LightColor0;
float _Shininess;
float _SpecularIntensity;
//float4 _AmbientColor;
sampler2D _SpecMask;
float _SpecMask_ST;
sampler2D _NormalMap;
float4 _NormalMap_ST;
float _NormalIntensity;
sampler2D _Parallax;
float _ParallaxIntensity;
float _HeightTime;
//float __AmbientIntensity;



v2f vert (appdata v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.normali_dir = normalize(mul(float4(v.normal,0.0),unity_WorldToObject).xyz);
o.tangent_dir = normalize(mul(float4(v.tangent.xyz,0.0),unity_WorldToObject).xyz);
o.binormal_dir = normalize(cross(o.normali_dir,o.tangent_dir))* v.tangent.w;
o.pos_world = mul(unity_ObjectToWorld,v.vertex).xyz;
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
TRANSFER_VERTEX_TO_FRAGMENT(o);
return o;
}

fixed4 frag (v2f i) : SV_Target
{
fixed4 col=fixed4(0,0,0,0);


half atten = LIGHT_ATTENUATION (i);
half4 normalmap = tex2D(_NormalMap,i.uv);
half3 view_dir = normalize(_WorldSpaceCameraPos.xyz - i.pos_world);
half3 light_dir_point =normalize( _WorldSpaceLightPos0.xyz - i.pos_world);
half3 light_dir =normalize( _WorldSpaceLightPos0.xyz );
light_dir = lerp(light_dir,light_dir_point,_WorldSpaceLightPos0.w);
half3 half_dir = normalize(view_dir+light_dir);
//Normal
half3 normal_dir =normalize(i.normali_dir);
half3 tangent_dir =normalize(i.tangent_dir)*_NormalIntensity;
half3 binormal_dir =normalize(i.binormal_dir)*_NormalIntensity;
half3 normal_data = UnpackNormal(normalmap);
float3x3 TBN = float3x3(tangent_dir,binormal_dir,normal_dir);
normal_dir =normalize(mul(normal_data,TBN));
//normal_dir=tangent_dir*normal_data.x*_NormalIntensity+binormal_dir*normal_data.y*_NormalIntensity+normal_dir*normal_data.z ;

float3 view_tangentspace = normalize(mul(TBN,view_dir));
half2 uv_parallax = i.uv;
for(int j=0;j<_HeightTime;j++)
{
half height = tex2D(_Parallax,uv_parallax);
uv_parallax = uv_parallax - (0.5 - height) * (view_tangentspace.xy/view_tangentspace.z+0.42) *_ParallaxIntensity*0.01f;
}
half3 base_color = tex2D(_MainTex, uv_parallax).xyz;

half3 AO = tex2D(_AOMap,uv_parallax).xyz;
half3 spec_mask = tex2D(_SpecMask,uv_parallax).xyz;


half NotL = min(atten,max(dot(normal_dir,light_dir),0));
half NotH = max(dot(normal_dir,half_dir),0);
half3 diffuse = NotL*_LightColor0.xyz;
half3 specular = pow(max(NotH,0),_Shininess)* _LightColor0.xyz*_SpecularIntensity*spec_mask*NotL;

col.xyz += diffuse;
col.xyz += specular;


// sample the texture
col.xyz *=base_color;
col.xyz *=AO;

// apply fog
return col;
}
ENDCG
}
}
FallBack "Diffuse"
}