-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathOneWayTrip
334 lines (296 loc) · 11.8 KB
/
OneWayTrip
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
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
//https://www.shadertoy.com/view/WlSSWV
float det=.005, fin=0., time; // 光线前进的起点,辅助变量
const float maxdist=60.; // 光线前进的最大距离
vec3 ldir=vec3(0.,1.,4.); // 光线向量 (没有归一化)
vec3 fcol; // 全局颜色
vec3 suncol=vec3(2.,1.,.6); // 太阳颜色
// 2D旋转函数
mat2 rot2D(float a) {
float s=sin(a);
float c=cos(a);
return mat2(c,s,-s,c);
}
//带角度的logo设计
mat2 rot2Ddeg(float a) {
a=radians(a);
float s=sin(a);
float c=cos(a);
return mat2(c,s,-s,c);
}
// -------------------------------------------------------------------------------------------
// PVM LOGO
// 带倾斜失真的2D矩形
float rect(vec2 p, vec2 b, float inc) {
p.x+=p.y*inc;
vec2 d = abs(p)-b;
return length(max(d,vec2(0))) + min(max(d.x,d.y),0.0);
}
// Inigo Quietz写的2D三角形
float tri(vec2 p, vec2 q, float ang) {
p*=rot2Ddeg(ang);
p.x = abs(p.x);
vec2 a = p - q*clamp( dot(p,q)/dot(q,q), 0.0, 1.0 );
vec2 b = p - q*vec2( clamp( p.x/q.x, 0.0, 1.0 ), 1.0 );
float s = -sign( q.y );
vec2 d = min( vec2( dot(a,a), s*(p.x*q.y-p.y*q.x) ),
vec2( dot(b,b), s*(p.y-q.y) ));
return -sqrt(d.x)*sign(d.y);
}
// 变形的矩形和三角形组成了logo
vec4 logo(vec2 uv) {
uv*=1.2;
uv.x*=1.15;
uv.y-=.6;
uv.x-=1.3;
float d=rect(uv,vec2(.045,.25),-.5);
uv.x+=.25;
uv.y+=.01;
d=min(d,rect(uv,vec2(.045,.24),.5));
uv.x+=.265;
uv.y-=.04;
d=min(d,rect(uv,vec2(.045,.2),-.55));
uv.x-=.73;
uv.y-=.06;
d=min(d,rect(uv,vec2(.045,.16),.4));
uv.x-=.105;
uv.y+=.074;
d=min(d,rect(uv,vec2(.045,.085),-.45));
uv.x-=.105;
uv.y+=.045;
d=min(d,rect(uv,vec2(.045,.13),.45));
uv.x-=.25;
uv.y+=.1;
d=min(d,rect(uv,vec2(.18,.03),.0));
uv.x+=1.32;
uv.y-=.18;
d=min(d,rect(uv+vec2(0.0,.03),vec2(.35,.03),.0));
uv.x-=.5165;
uv.y+=.4;
d=min(d,tri(uv,vec2(.09,.185),0.));
uv.x-=.492;
uv.y-=.56;
d=min(d,tri(uv,vec2(.063,.14),180.));
uv.x+=.225;
uv.y-=.17;
d=min(d,tri(uv,vec2(.063,.145),180.));
uv.x-=.142;
uv.y+=.555;
d=min(d,tri(uv,vec2(.063,.145),0.));
uv.x+=.985;
uv.y+=.075;
vec2 uvd=uv-vec2(uv.y,0.);
d=min(d,tri(uvd-vec2(0.003,0.022),vec2(.04,.05),0.));
uv.x-=.16 ;
uv.y-=.63;
uvd=uv+vec2(uv.y*.4,0.);
d=min(d,tri(uvd+vec2(.03,0.),vec2(.07,.23),-145.));
uvd=uv+vec2(.465,.33);
uvd*=rot2Ddeg(27.);
uvd-=vec2(uvd.y*.5*sign(uvd.x),0.);
d=min(d,rect(uvd,vec2(.08,.03),.0));
uvd=uv+vec2(-1.43,.534);
uvd*=rot2Ddeg(206.);
uvd-=vec2(uvd.y*.5*sign(uvd.x),0.);
d=min(d,rect(uvd,vec2(.08,.03),.0));
float s=pow(abs(d)+.9,10.);
uvd=uv+vec2(-.28,.36);
uvd*=rot2Ddeg(50.);
d=max(d,-rect(uvd,vec2(.1,.025),.0));
// logo着色, RGBA
float o=1.-smoothstep(0.,.01,d);
float l=1.-smoothstep(0.,.05,d);
vec3 col=mix(vec3(2.,.15,.1),vec3(1.,2.,.5),min(1.,abs(uv.y+.4)));
return vec4(col*o+.1,l);
}
// -------------------------------------------------------------------------------------------
// 分形
// 一堆三角函数定义了分形曲线,返回曲线上给定点的位移,使用freq(频率)参数进行不同的缩放
vec3 pitpath(float ti) {
float freq=.5;
ti*=freq;
float x=cos(cos(ti*.35682)+ti*.2823)*cos(ti*.1322)*1.5;
float y=sin(ti*.166453)*4.+cos(cos(ti*.125465)+ti*.17354)*cos(ti*.05123)*2.;
vec3 p=vec3(x,y,ti/freq);
return p;
}
//距离判断函数
float de(vec3 pos) {
float x=1.-smoothstep(5.,8.,abs(pos.x)); // 辅助变量,用来洗掉分形曲线上的颜色
pos.y+=.9; // 分形对象的y值偏移
pos.xy-=pitpath(pos.z).xy; // 基于分形曲线函数的坐标变形
mat2 rot=rot2D(.5); // 用于分形迭代循环的旋转矩阵
float organic=smoothstep(.5,1.,-sin(pos.z*.005)); // 用于分形的“有机”部分
mat2 rot2=rot2D(organic*.4); // 用于分形迭代循环的旋转矩阵,将分形变成“有机”形状
float fold=2.6+sin(pos.z*.01)+organic*1.5; // 褶皱是分形循环中某个步骤的参数
pos.x+=pow(organic,.2)*fold*.75; // 有机部分的x方向偏移
pos.y+=organic*.3; // 有机部分的y方向偏移
pos.z=abs(5.-mod(pos.z,10.)); // 沿z方向平铺重复分形
pos.x=abs(10.-mod(pos.x+10.,20.)); // 沿x方向平铺重复分形
pos.x-=fold; //到分形中心的x方向偏移量
vec4 p=vec4(pos,1.); // w分量用来计算衍生物
vec3 m=vec3(1000.); // 用于轨道陷阱着色
int it=int(8.+fin*2.); // 在结尾给分形更多迭代
// Kali制作的表面分形方程,来源于tglad的Mandelbox
for (int i=0; i<it; i++) {
p.xz=clamp(p.xz,-vec2(fold,2.),vec2(fold,2.))*2.0-p.xz; // xz平面上的褶皱变换
p.xyz-=vec3(.5,.8,1.); // 平移变换
p=p*(2.-organic*.2)/clamp(dot(p.xyz,p.xyz),.25,1.)-vec4(2.,.5,-1.,0.)*x; // 缩放+球面褶皱+平移变换
//旋转变换
p.xy*=rot;
p.xz*=rot2; //xz和yz平面上的旋转给予“异形珊瑚礁”一种有机质感
p.yz*=rot2;
m=min(m,abs(p.xyz)); // 迭代期间保存位置的最小值,用于“轨道陷阱”着色
}
// 分形着色 (fcol全局变量)
fcol=vec3(1.,.3,.0)*m*x;
fcol=max(fcol,length(p)*.0015*vec3(1.,.9,.8)*(1.-fin))*(1.+organic*.5);
return (max(p.x,p.y)/p.w-.025*(1.-fin))*.85; // 将距离判断值返回到分形表面,最后进行一些调整
}
// -------------------------------------------------------------------------------------------
// 光线前进
// 将给定点的垂直向量返回到表面
vec3 normal(vec3 p) {
vec3 d=vec3(0.,det*2.,0.);
return normalize(vec3(de(p-d.yxx),de(p-d.xyx), de(p-d.xxy))-de(p));
}
// 环境光遮蔽与软阴影,IQ的经典方法
float ao(vec3 p, vec3 n) {
float td=0., ao=0.;
for(int i=0; i<6; i++) {
td+=.05;
float d=de(p-n*td);
ao+=max(0.,(td-d)/td);
}
return clamp(1.-ao*.1,0.,1.);
}
float shadow(vec3 p) {
float sh=1.,td=.1;
for (int i=0; i<50; i++) {
p+=ldir*td;
float d=de(p);
td+=d;
sh=min(sh,10.*d/td);
if (sh<.05) break;
}
return clamp(sh,0.,1.);
}
// 光照
vec3 shade(vec3 p, vec3 dir, vec3 n, vec3 col) {
float sha=shadow(p);
float aoc=ao(p,n);
float amb=.25*aoc; // 带遮蔽的环境光
float dif=max(0.,dot(ldir,-n))*sha; // 带阴影的漫射光
vec3 ref=reflect(dir,n); // 反射向量
float spe=pow(max(0.,dot(ldir,ref)),10.)*.7*sha; // 镜面反射光
return col*(amb+dif)+spe*suncol; // 光照应用到表面颜色
}
// 光照前进
vec4 march(vec3 from, vec3 dir, vec3 camdir) {
//变量声明
vec3 p=from, col=vec3(0.1), backcol=col;
float totdist=0., d=0.,sdet, glow=0., lhit=1.;
// 随着接近分形的边界,细节值(detail)会逐渐变小
det*=1.-fin*.7;
// 光线前进循环,用来容纳照相机方向上的太阳环境光
// 用于镜头光晕
for (int i=0; i<70; i++) {
p+=d*ldir; // 将光线从照相机位置推到光照向量
d=de(p)*2.; // 距离估测,由于不必太精确,所以*2以节约性能
lhit=min(lhit,d);//光线遮挡值,取决于光线离表面的距离,与表面碰撞时会非常小
if (d<det) { // 光线击中表面,完成
break;
}
}
// 光照前进主循环
for (int i=0; i<150; i++) {
p=from+totdist*dir; // 推进光线
d=de(p); // 到分形表面的距离估测
sdet=det*(1.+totdist*.1); // 远处的碰撞会使细节等级更低
if (d<sdet||totdist>maxdist) break; // 光线击中表面,或者达到最大距离
totdist+=d; // 距离累加
glow++; // 步进,用于荧光效果
}
float sun=max(0.,dot(dir,ldir)); // 照相机向量和光照向量的点乘,用于画太阳
if (d<.2) { // 光线大多数会击中表面
p-=(sdet-d)*dir; // 后退以校正射线位置
vec3 c=fcol; // //保存de()函数设定的颜色值,这样就不会被归一化计算所替换
vec3 n=normal(p); // 在光线命中点归一化计算
col=shade(p,dir,n,c); // 设定颜色和光照
} else { // 光线没有遇到任何表面,即为背景
totdist=maxdist;
p=from+dir*maxdist; // 将光线移动到最大距离
// 太阳附近的星尘的Kali分形方程
vec3 st = (dir * 3.+ vec3(1.3,2.5,1.25)) * .3;
for (int i = 0; i < 10; i++) st = abs(st) / dot(st,st) - .8;
backcol+=length(st)*.015*(1.-pow(sun,3.))*(.5+abs(st.grb)*.5);
sun-=length(st)*.0017;
sun=max(0.,sun);
backcol+=pow(sun,100.)*.5; // 背景加上太阳光
}
backcol+=pow(sun,20.)*suncol*.8; // 太阳光
float normdist=totdist/maxdist; // 射线的距离归一化
col=mix(col,backcol,pow(normdist,1.5)); // 远处将地面和背景融合(雾气)
col=max(col,col*vec3(sqrt(glow))*.13); // 添加一点荧光
// 镜头光晕
vec2 pflare=dir.xy-ldir.xy;
float flare=max(0.,1.0-length(pflare))-pow(abs(1.-mod(camdir.x-atan(pflare.y,pflare.x)*5./3.14,2.)),.6);
float cflare=pow(max(0.,dot(camdir,ldir)),20.)*lhit;
col+=pow(max(0.,flare),3.)*cflare*suncol;
col+=pow(sun,30.)*cflare;
// "只有荧光" 部分(在大约10s时)
col.rgb=mix(col.rgb,glow*suncol*.01+backcol,1.-smoothstep(0.,.8,abs(time-10.5)));
return vec4(col,normdist); // 返回最终颜色值,和在alpha中归一化的深度值
} //(深度值用于后期处理着色器)
// -------------------------------------------------------------------------------------------
// 照相机和mainImage
// eiffie的函数,传入一个向量,参考的上方向,返回旋转矩阵以朝向向量
mat3 lookat(vec3 dir, vec3 up){
dir=normalize(dir);vec3 rt=normalize(cross(dir,normalize(up)));
return mat3(rt,cross(rt,dir),dir);
}
// 在给定时间点,照相机的路径
vec3 campath(float ti) {
float start=pow(max(0.,1.-ti*.02),3.); // 起始照相机的插值曲线
vec3 p=pitpath(ti); // 分形曲线的位移
p*=1.-start; //照相机最后逐渐跟随分形曲线,当start=0的时候发生
p+=vec3(start*30.,start*25.,0.); //照相机曲线开始时的位置偏移
return p;
}
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
vec2 uv=fragCoord/iResolution.xy-.5;
uv.x*=iResolution.x/iResolution.y;
vec3 dir=normalize(vec3(uv,1.)); // 光线向量
time=mod(iTime,162.); // 时间循环
fin=smoothstep(145.,147.5,time); // 结束时的辅助变量
// 照相机的加速和减速
float acel1=smoothstep(11.,12.,time)*7.31;
float acel2=smoothstep(99.,100.,time)*4.;
float desacel1=smoothstep(77.,78.,time)*5.;
float desacel2=fin*9.5;
float tt=time;
//冻结BW帧
if (abs(tt-25.5)<.5) tt=25.;
float acel=acel1+acel2-desacel1-desacel2;
// 时间变量
float t=tt*(3.6+acel)-acel1*11.-acel2*99.+desacel1*77.+desacel2*147.5;
t+=smoothstep(125.,145.,time)*243.;
vec3 from=campath(t); // 照相机位置
from.y-=desacel2*.035; // 第二次减速时的照相机偏移
vec3 fw=normalize(campath(t+3.)-from); // 照相机朝向向量
from.x-=fw.x*.1; // 照相机x方向偏移,取决于朝向
dir=dir*lookat(fw*vec3(1.,-1.,1.),vec3(fw.x*.2,1.,0.)); // 以照相机朝向重定向光线朝向
ldir=normalize(ldir); // 光线向量归一化
vec4 col=march(from, dir, fw); //从光线前进和背景中获取颜色
col.rgb=mix(vec3(length(col.rgb)*.6),col.rgb,.85-step(abs(tt-25.),.1)); // BW冻结帧的一系列颜色
col.rgb*=1.-smoothstep(25.,26.,time)+step(25.1,tt); // BW冻结帧淡入淡出
col.rgb*=1.+step(abs(tt-25.),.1);
// PVM Logo 颜色混合
vec4 pvm=logo(uv*1.5+vec2(.9,.5))*smoothstep(1.,3.,time+uv.x*2.)*(1.-smoothstep(7.5,8.,time+uv.x*2.));
col.rgb=mix(col.rgb,pvm.rgb,pvm.a);
// 从黑色淡入
col.rgb*=smoothstep(0.,4.,time);
// 从黑色淡出
col.rgb*=1.-smoothstep(160.,162.,time);
fragColor = col;
}