/
SceneryShader.fx
757 lines (659 loc) · 23.6 KB
/
SceneryShader.fx
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
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
// COPYRIGHT 2009, 2010, 2011, 2012, 2013 by the Open Rails project.
//
// This file is part of Open Rails.
//
// Open Rails is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Open Rails is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Open Rails. If not, see <http://www.gnu.org/licenses/>.
// This file is the responsibility of the 3D & Environment Team.
////////////////////////////////////////////////////////////////////////////////
// S C E N E R Y O B J E C T S H A D E R //
////////////////////////////////////////////////////////////////////////////////
//////////////////// G L O B A L V A L U E S ///////////////////////////
float4x4 World; // model -> world
float4x4 View; // world -> view
float4x4 Projection; // view -> projection
float4x4 LightViewProjectionShadowProjection0; // world -> light view -> light projection -> shadow map projection
float4x4 LightViewProjectionShadowProjection1;
float4x4 LightViewProjectionShadowProjection2;
float4x4 LightViewProjectionShadowProjection3;
texture ShadowMapTexture0;
texture ShadowMapTexture1;
texture ShadowMapTexture2;
texture ShadowMapTexture3;
float4 ShadowMapLimit;
float4 ZBias_Lighting; // x = z-bias, y = diffuse, z = specular, w = step(1, z)
float4 Fog; // rgb = color of fog; a = reciprocal of distance from camera, everything is
// normal color; FogDepth = FogStart, i.e. FogEnd = 2 * FogStart.
float4 LightVector_ZFar; // xyz = direction vector to sun (world), w = z-far distance
float4 HeadlightPosition; // xyz = position; w = lighting fading.
float4 HeadlightDirection; // xyz = normalized direction (length = distance to light); w = 0.5 * (1 - min dot product).
float HeadlightRcpDistance; // reciprocal length = reciprocal distance to light
float4 HeadlightColor; // rgba = color
float2 Overcast; // Lower saturation & brightness when overcast. x = FullBrightness, y = HalfBrightness
float3 ViewerPos; // Viewer's world coordinates.
float ImageTextureIsNight;
float NightColorModifier;
float HalfNightColorModifier;
float VegetationAmbientModifier;
float SignalLightIntensity;
float4 EyeVector;
float3 SideVector;
float ReferenceAlpha;
texture ImageTexture;
texture OverlayTexture;
float OverlayScale;
sampler Image = sampler_state
{
Texture = (ImageTexture);
MagFilter = Linear;
MinFilter = Anisotropic;
MipFilter = Linear;
MaxAnisotropy = 16;
};
sampler Overlay = sampler_state
{
Texture = (OverlayTexture);
MagFilter = Linear;
MinFilter = Linear;
MipFilter = Linear;
MipLodBias = 0;
AddressU = Wrap;
AddressV = Wrap;
};
sampler ShadowMap0 = sampler_state
{
Texture = (ShadowMapTexture0);
MagFilter = Linear;
MinFilter = Linear;
MipFilter = Linear;
};
sampler ShadowMap1 = sampler_state
{
Texture = (ShadowMapTexture1);
MagFilter = Linear;
MinFilter = Linear;
MipFilter = Linear;
};
sampler ShadowMap2 = sampler_state
{
Texture = (ShadowMapTexture2);
MagFilter = Linear;
MinFilter = Linear;
MipFilter = Linear;
};
sampler ShadowMap3 = sampler_state
{
Texture = (ShadowMapTexture3);
MagFilter = Linear;
MinFilter = Linear;
MipFilter = Linear;
};
//////////////////// V E R T E X I N P U T S ///////////////////////////
struct VERTEX_INPUT
{
float4 Position : POSITION;
float2 TexCoords : TEXCOORD0;
float3 Normal : NORMAL;
float4x4 Instance : TEXCOORD1;
};
struct VERTEX_INPUT_FOREST
{
float4 Position : POSITION;
float2 TexCoords : TEXCOORD0;
float3 Normal : NORMAL;
};
struct VERTEX_INPUT_SIGNAL
{
float4 Position : POSITION;
float2 TexCoords : TEXCOORD0;
float4 Color : COLOR0;
};
struct VERTEX_INPUT_TRANSFER
{
float4 Position : POSITION;
float2 TexCoords : TEXCOORD0;
};
//////////////////// V E R T E X O U T P U T S /////////////////////////
struct VERTEX_OUTPUT
{
float4 Position : POSITION; // position x, y, z, w
float4 RelPosition : TEXCOORD0; // rel position x, y, z; position z
float2 TexCoords : TEXCOORD1; // tex coords x, y
float4 Color : COLOR0; // color r, g, b, a
float4 Normal_Light : TEXCOORD2; // normal x, y, z; light dot
float4 LightDir_Fog : TEXCOORD3; // light dir x, y, z; fog fade
float4 Shadow : TEXCOORD4; // Level9_1<shadow map texture and depth x, y, z> Level9_3<abs position x, y, z, w>
};
//////////////////// V E R T E X S H A D E R S /////////////////////////
void _VSNormalProjection(in VERTEX_INPUT In, inout VERTEX_OUTPUT Out)
{
// Project position, normal and copy texture coords
Out.Position = mul(mul(mul(In.Position, World), View), Projection);
Out.RelPosition.xyz = mul(In.Position, World).xyz - ViewerPos;
Out.RelPosition.w = Out.Position.z;
Out.TexCoords.xy = In.TexCoords;
Out.Normal_Light.xyz = normalize(mul(In.Normal, (float3x3)World).xyz);
// Normal lighting (range 0.0 - 1.0)
// Need to calc. here instead of _VSLightsAndShadows() to avoid calling it from VSForest(), where it has gone into pre-shader in Shaders.cs
Out.Normal_Light.w = dot(Out.Normal_Light.xyz, LightVector_ZFar.xyz) * 0.5 + 0.5;
}
void _VSSignalProjection(uniform bool Glow, in VERTEX_INPUT_SIGNAL In, inout VERTEX_OUTPUT Out)
{
// Project position, normal and copy texture coords
float3 relPos = mul(In.Position, World).xyz - ViewerPos;
// Position 1.5cm in front of signal.
In.Position.z += 0.015;
if (Glow) {
// Position glow a further 1.5cm in front of the light.
In.Position.z += 0.015;
// The glow around signal lights scales according to distance; there is a cut-off which controls when the glow
// starts, a scaling factor which determines how quickly it expands (logarithmically), and ZBias_Lighting.x is
// an overall "glow power" control which determines the effectiveness of glow on any individual light. This is
// used to have different glows in the day and night, and to prevent theatre boxes from glowing!
const float GlowCutOffM = 100;
const float GlowScalingFactor = 40;
In.Position.xyz *= log(1 + max(0, length(relPos) - GlowCutOffM) / GlowScalingFactor) * ZBias_Lighting.x;
}
Out.Position = mul(mul(mul(In.Position, World), View), Projection);
Out.RelPosition.xyz = relPos;
Out.RelPosition.w = Out.Position.z;
Out.TexCoords.xy = In.TexCoords;
Out.Color = In.Color;
}
void _VSTransferProjection(in VERTEX_INPUT_TRANSFER In, inout VERTEX_OUTPUT Out)
{
// Project position, normal and copy texture coords
Out.Position = mul(mul(mul(In.Position, World), View), Projection);
Out.RelPosition.xyz = mul(In.Position, World).xyz - ViewerPos;
Out.RelPosition.w = Out.Position.z;
Out.TexCoords.xy = In.TexCoords;
Out.Normal_Light.w = 1;
}
void _VSLightsAndShadows(uniform bool ShaderModel3, in float4 InPosition, inout VERTEX_OUTPUT Out)
{
// Headlight lighting
Out.LightDir_Fog.xyz = mul(InPosition, World).xyz - HeadlightPosition.xyz;
// Fog fading
Out.LightDir_Fog.w = (2.0 / (1.0 + exp(length(Out.Position.xyz) * Fog.a * -2.0))) - 1.0;
// Absolute position for shadow mapping
if (ShaderModel3) {
Out.Shadow = mul(InPosition, World);
} else {
Out.Shadow.xyz = mul(mul(InPosition, World), LightViewProjectionShadowProjection0).xyz;
}
}
VERTEX_OUTPUT VSGeneral(uniform bool ShaderModel3, in VERTEX_INPUT In)
{
VERTEX_OUTPUT Out = (VERTEX_OUTPUT)0;
if (ShaderModel3) {
if (determinant(In.Instance) != 0) {
In.Position = mul(In.Position, transpose(In.Instance));
In.Normal = mul(In.Normal, (float3x3)transpose(In.Instance));
}
}
_VSNormalProjection(In, Out);
_VSLightsAndShadows(ShaderModel3, In.Position, Out);
// Z-bias to reduce and eliminate z-fighting on track ballast. ZBias is 0 or 1.
Out.Position.z -= ZBias_Lighting.x * saturate(In.TexCoords.x) / 1000;
return Out;
}
VERTEX_OUTPUT VSGeneral9_3(in VERTEX_INPUT In)
{
return VSGeneral(true, In);
}
VERTEX_OUTPUT VSGeneral9_1(in VERTEX_INPUT In)
{
return VSGeneral(false, In);
}
VERTEX_OUTPUT VSTransfer(uniform bool ShaderModel3, in VERTEX_INPUT_TRANSFER In)
{
VERTEX_OUTPUT Out = (VERTEX_OUTPUT)0;
_VSTransferProjection(In, Out);
_VSLightsAndShadows(ShaderModel3, In.Position, Out);
// Z-bias to reduce and eliminate z-fighting on track ballast. ZBias is 0 or 1.
Out.Position.z -= ZBias_Lighting.x * saturate(In.TexCoords.x) / 1000;
return Out;
}
VERTEX_OUTPUT VSTransfer3(in VERTEX_INPUT_TRANSFER In)
{
return VSTransfer(true, In);
}
VERTEX_OUTPUT VSTransfer9_1(in VERTEX_INPUT_TRANSFER In)
{
return VSTransfer(false, In);
}
VERTEX_OUTPUT VSTerrain(uniform bool ShaderModel3, in VERTEX_INPUT In)
{
VERTEX_OUTPUT Out = (VERTEX_OUTPUT)0;
_VSNormalProjection(In, Out);
_VSLightsAndShadows(ShaderModel3, In.Position, Out);
return Out;
}
VERTEX_OUTPUT VSTerrain9_3(in VERTEX_INPUT In)
{
return VSTerrain(true, In);
}
VERTEX_OUTPUT VSTerrain9_1(in VERTEX_INPUT In)
{
return VSTerrain(false, In);
}
VERTEX_OUTPUT VSForest(in VERTEX_INPUT_FOREST In)
{
VERTEX_OUTPUT Out = (VERTEX_OUTPUT)0;
// Start with the three vectors of the view.
float3 upVector = float3(0, -1, 0); // This constant is also defined in Shareds.cs
// Move the vertex left/right/up/down based on the normal values (tree size).
float3 newPosition = In.Position.xyz;
newPosition += (In.TexCoords.x - 0.5f) * SideVector * In.Normal.x;
newPosition += (In.TexCoords.y - 1.0f) * upVector * In.Normal.y;
In.Position = float4(newPosition, 1);
// Project vertex with fixed w=1 and normal=eye.
Out.Position = mul(mul(mul(In.Position, World), View), Projection);
Out.RelPosition.xyz = mul(In.Position, World).xyz - ViewerPos;
Out.RelPosition.w = Out.Position.z;
Out.TexCoords.xy = In.TexCoords;
Out.Normal_Light = EyeVector;
_VSLightsAndShadows(false, In.Position, Out);
return Out;
}
VERTEX_OUTPUT VSSignalLight(in VERTEX_INPUT_SIGNAL In)
{
VERTEX_OUTPUT Out = (VERTEX_OUTPUT)0;
_VSSignalProjection(false, In, Out);
return Out;
}
VERTEX_OUTPUT VSSignalLightGlow(in VERTEX_INPUT_SIGNAL In)
{
VERTEX_OUTPUT Out = (VERTEX_OUTPUT)0;
_VSSignalProjection(true, In, Out);
return Out;
}
//////////////////// P I X E L S H A D E R S ///////////////////////////
// Gets the ambient light effect.
float _PSGetAmbientEffect(in VERTEX_OUTPUT In)
{
return In.Normal_Light.w * ZBias_Lighting.y;
}
// Gets the specular light effect.
float _PSGetSpecularEffect(in VERTEX_OUTPUT In)
{
float3 halfVector = normalize(-In.RelPosition.xyz) + LightVector_ZFar.xyz;
return In.Normal_Light.w * ZBias_Lighting.w * pow(saturate(dot(In.Normal_Light.xyz, normalize(halfVector))), ZBias_Lighting.z);
}
// Gets the shadow effect.
float3 _Level9_1GetShadowEffect(in VERTEX_OUTPUT In)
{
return float3(tex2D(ShadowMap0, In.Shadow.xy).xy, In.Shadow.z);
}
float3 _Level9_3GetShadowEffect(in VERTEX_OUTPUT In)
{
float depth = In.RelPosition.w;
float3 rv = 0;
if (depth < ShadowMapLimit.x) {
float3 pos0 = mul(In.Shadow, LightViewProjectionShadowProjection0).xyz;
rv = float3(tex2D(ShadowMap0, pos0.xy).xy, pos0.z);
} else {
if (depth < ShadowMapLimit.y) {
float3 pos1 = mul(In.Shadow, LightViewProjectionShadowProjection1).xyz;
rv = float3(tex2D(ShadowMap1, pos1.xy).xy, pos1.z);
} else {
if (depth < ShadowMapLimit.z) {
float3 pos2 = mul(In.Shadow, LightViewProjectionShadowProjection2).xyz;
rv = float3(tex2D(ShadowMap2, pos2.xy).xy, pos2.z);
} else {
if (depth < ShadowMapLimit.w) {
float3 pos3 = mul(In.Shadow, LightViewProjectionShadowProjection3).xyz;
rv = float3(tex2D(ShadowMap3, pos3.xy).xy, pos3.z);
}
}
}
}
return rv;
}
void _PSApplyShadowColor(inout float3 Color, in VERTEX_OUTPUT In)
{
float depth = In.RelPosition.w;
if (depth < ShadowMapLimit.x) {
Color.rgb *= 0.9;
Color.r += 0.1;
} else {
if (depth < ShadowMapLimit.y) {
Color.rgb *= 0.9;
Color.g += 0.1;
} else {
if (depth < ShadowMapLimit.z) {
Color.rgb *= 0.9;
Color.b += 0.1;
} else {
if (depth < ShadowMapLimit.w) {
Color.rgb *= 0.9;
Color.rg += 0.1;
}
}
}
}
}
float _PSGetShadowEffect(uniform bool ShaderModel3, uniform bool NormalLighting, in VERTEX_OUTPUT In)
{
float3 moments;
if (ShaderModel3)
moments = _Level9_3GetShadowEffect(In);
else
moments = _Level9_1GetShadowEffect(In);
bool not_shadowed = moments.z - moments.x < 0.00005;
float E_x2 = moments.y;
float Ex_2 = moments.x * moments.x;
float variance = clamp(E_x2 - Ex_2, 0.00005, 1.0);
float m_d = moments.z - moments.x;
float p = pow(variance / (variance + m_d * m_d), 50);
if (NormalLighting)
return saturate(not_shadowed + p) * saturate(In.Normal_Light.w * 5 - 2);
return saturate(not_shadowed + p);
}
// Gets the overcast color.
float3 _PSGetOvercastColor(in float4 Color, in VERTEX_OUTPUT In)
{
// Value used to determine equivalent grayscale color.
const float3 LumCoeff = float3(0.2125, 0.7154, 0.0721);
float intensity = dot(Color.rgb, LumCoeff);
return lerp(intensity, Color.rgb, 0.8) * 0.5;
}
// Applies the lighting effect of the train's headlights, including
// fade-in/fade-out animations.
void _PSApplyHeadlights(inout float3 Color, in float3 OriginalColor, in VERTEX_OUTPUT In)
{
float3 headlightToSurface = normalize(In.LightDir_Fog.xyz);
float coneDot = dot(headlightToSurface, HeadlightDirection.xyz);
float shading = step(0, coneDot);
shading *= step(0, dot(In.Normal_Light.xyz, -headlightToSurface));
shading *= saturate(HeadlightDirection.w / (1 - coneDot));
shading *= saturate(1 - length(In.LightDir_Fog.xyz) * HeadlightRcpDistance);
shading *= HeadlightPosition.w;
Color += OriginalColor * HeadlightColor.rgb * HeadlightColor.a * shading;
}
// Applies distance fog to the pixel.
void _PSApplyFog(inout float3 Color, in VERTEX_OUTPUT In)
{
Color = lerp(Color, Fog.rgb, In.LightDir_Fog.w);
}
void _PSSceneryFade(inout float4 Color, in VERTEX_OUTPUT In)
{
if (ReferenceAlpha < 0.01) Color.a = 1;
Color.a *= saturate((LightVector_ZFar.w - length(In.RelPosition.xyz)) / 50);
}
float4 PSImage(uniform bool ShaderModel3, uniform bool ClampTexCoords, in VERTEX_OUTPUT In) : COLOR0
{
const float FullBrightness = 1.0;
const float ShadowBrightness = 0.5;
float4 Color = tex2D(Image, In.TexCoords.xy);
if (ShaderModel3 && ClampTexCoords) {
// We need to clamp the rendering to within the [0..1] range only.
if (saturate(In.TexCoords.x) != In.TexCoords.x || saturate(In.TexCoords.y) != In.TexCoords.y) {
Color.a = 0;
}
}
// Alpha testing:
clip(Color.a - ReferenceAlpha);
// Ambient and shadow effects apply first; night-time textures cancel out all normal lighting.
float3 litColor = Color.rgb * lerp(ShadowBrightness, FullBrightness, saturate(_PSGetAmbientEffect(In) * _PSGetShadowEffect(ShaderModel3, true, In) + ImageTextureIsNight));
// Specular effect next.
litColor += _PSGetSpecularEffect(In) * _PSGetShadowEffect(ShaderModel3, true, In);
// Overcast blanks out ambient, shadow and specular effects (so use original Color).
litColor = lerp(litColor, _PSGetOvercastColor(Color, In), Overcast.x);
// Night-time darkens everything, except night-time textures.
litColor *= NightColorModifier;
// Headlights effect use original Color.
_PSApplyHeadlights(litColor, Color.rgb, In);
// And fogging is last.
_PSApplyFog(litColor, In);
if (ShaderModel3) _PSSceneryFade(Color, In);
//if (ShaderModel3) _PSApplyShadowColor(litColor, In);
return float4(litColor, Color.a);
}
float4 PSImage9_3(in VERTEX_OUTPUT In) : COLOR0
{
return PSImage(true, false, In);
}
float4 PSImage9_3Clamp(in VERTEX_OUTPUT In) : COLOR0
{
return PSImage(true, true, In);
}
float4 PSImage9_1(in VERTEX_OUTPUT In) : COLOR0
{
return PSImage(false, false, In);
}
float4 PSVegetation(in VERTEX_OUTPUT In) : COLOR0
{
float4 Color = tex2D(Image, In.TexCoords.xy);
// Alpha testing:
clip(Color.a - ReferenceAlpha);
// Ambient effect applies first; no shadow effect for vegetation; night-time textures cancel out all normal lighting.
float3 litColor = Color.rgb * VegetationAmbientModifier;
// No specular effect for vegetation.
// Overcast blanks out ambient, shadow and specular effects (so use original Color).
litColor = lerp(litColor, _PSGetOvercastColor(Color, In), Overcast.x);
// Night-time darkens everything, except night-time textures.
litColor *= NightColorModifier;
// Headlights effect use original Color.
_PSApplyHeadlights(litColor, Color.rgb, In);
// And fogging is last.
_PSApplyFog(litColor, In);
_PSSceneryFade(Color, In);
return float4(litColor, Color.a);
}
float4 PSTerrain(uniform bool ShaderModel3, in VERTEX_OUTPUT In) : COLOR0
{
const float FullBrightness = 1.0;
const float ShadowBrightness = 0.5;
float4 Color = tex2D(Image, In.TexCoords.xy);
// Ambient and shadow effects apply first; night-time textures cancel out all normal lighting.
float3 litColor = Color.rgb * lerp(ShadowBrightness, FullBrightness, saturate(_PSGetAmbientEffect(In) * _PSGetShadowEffect(ShaderModel3, true, In) + ImageTextureIsNight));
// No specular effect for terrain.
// Overcast blanks out ambient, shadow and specular effects (so use original Color).
litColor = lerp(litColor, _PSGetOvercastColor(Color, In), Overcast.x);
// Night-time darkens everything, except night-time textures.
litColor *= NightColorModifier;
// Overlay image for terrain.
litColor.rgb *= tex2D(Overlay, In.TexCoords.xy * OverlayScale).rgb * 2;
// Headlights effect use original Color.
_PSApplyHeadlights(litColor, Color.rgb, In);
// And fogging is last.
_PSApplyFog(litColor, In);
_PSSceneryFade(Color, In);
//if (ShaderModel3) _PSApplyShadowColor(litColor, In);
return float4(litColor, Color.a);
}
float4 PSTerrain9_3(in VERTEX_OUTPUT In) : COLOR0
{
return PSTerrain(true, In);
}
float4 PSTerrain9_1(in VERTEX_OUTPUT In) : COLOR0
{
return PSTerrain(false, In);
}
float4 PSDarkShade(in VERTEX_OUTPUT In) : COLOR0
{
const float ShadowBrightness = 0.5;
float4 Color = tex2D(Image, In.TexCoords.xy);
// Alpha testing:
clip(Color.a - ReferenceAlpha);
// Fixed ambient and shadow effects at darkest level.
float3 litColor = Color.rgb * ShadowBrightness;
// No specular effect for dark shade.
// Overcast blanks out ambient, shadow and specular effects (so use original Color).
litColor = lerp(litColor, _PSGetOvercastColor(Color, In), Overcast.x);
// Night-time darkens everything, except night-time textures.
litColor *= NightColorModifier;
// Headlights effect use original Color.
_PSApplyHeadlights(litColor, Color.rgb, In);
// And fogging is last.
_PSApplyFog(litColor, In);
_PSSceneryFade(Color, In);
return float4(litColor, Color.a);
}
float4 PSHalfBright(in VERTEX_OUTPUT In) : COLOR0
{
const float HalfShadowBrightness = 0.75;
float4 Color = tex2D(Image, In.TexCoords.xy);
// Alpha testing:
clip(Color.a - ReferenceAlpha);
// Fixed ambient and shadow effects at mid-dark level.
float3 litColor = Color.rgb * HalfShadowBrightness;
// No specular effect for half-bright.
// Overcast blanks out ambient, shadow and specular effects (so use original Color).
litColor = lerp(litColor, _PSGetOvercastColor(Color, In), Overcast.y);
// Night-time darkens everything, except night-time textures.
litColor *= HalfNightColorModifier;
// Headlights effect use original Color.
_PSApplyHeadlights(litColor, Color.rgb, In);
// And fogging is last.
_PSApplyFog(litColor, In);
_PSSceneryFade(Color, In);
return float4(litColor, Color.a);
}
float4 PSFullBright(in VERTEX_OUTPUT In) : COLOR0
{
float4 Color = tex2D(Image, In.TexCoords.xy);
// Alpha testing:
clip(Color.a - ReferenceAlpha);
// Fixed ambient and shadow effects at brightest level.
float3 litColor = Color.rgb;
// No specular effect for full-bright.
// No overcast effect for full-bright.
// No night-time effect for full-bright.
// Headlights effect use original Color.
_PSApplyHeadlights(litColor, Color.rgb, In);
// And fogging is last.
_PSApplyFog(litColor, In);
_PSSceneryFade(Color, In);
return float4(litColor, Color.a);
}
float4 PSSignalLight(in VERTEX_OUTPUT In) : COLOR0
{
float4 Color = tex2D(Image, In.TexCoords.xy);
// Alpha testing:
clip(Color.a - ReferenceAlpha);
// No ambient and shadow effects for signal lights.
// Apply signal coloring effect.
float3 litColor = lerp(Color.rgb, In.Color.rgb, Color.r);
// No specular effect, overcast effect, night-time darkening, headlights or fogging effect for signal lights.
return float4(litColor, Color.a * SignalLightIntensity);
}
//////////////////// T E C H N I Q U E S /////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// IMPORTANT: ATI graphics cards/drivers do NOT like mixing shader model //
// versions within a technique/pass. Always use the same vertex //
// and pixel shader versions within each technique/pass. //
////////////////////////////////////////////////////////////////////////////////
technique ImageLevel9_1 {
pass Pass_0 {
VertexShader = compile vs_4_0_level_9_1 VSGeneral9_1();
PixelShader = compile ps_4_0_level_9_1 PSImage9_1();
}
}
technique ImageLevel9_3 {
pass Pass_0 {
VertexShader = compile vs_4_0_level_9_3 VSGeneral9_3();
PixelShader = compile ps_4_0_level_9_3 PSImage9_3();
}
}
technique TransferLevel9_1 {
pass Pass_0 {
VertexShader = compile vs_4_0_level_9_1 VSTransfer9_1();
PixelShader = compile ps_4_0_level_9_1 PSImage9_1();
}
}
technique TransferLevel9_3 {
pass Pass_0 {
VertexShader = compile vs_4_0_level_9_3 VSTransfer3();
PixelShader = compile ps_4_0_level_9_3 PSImage9_3Clamp();
}
}
technique Forest {
pass Pass_0 {
VertexShader = compile vs_4_0_level_9_1 VSForest();
PixelShader = compile ps_4_0_level_9_1 PSVegetation();
}
}
technique VegetationLevel9_1 {
pass Pass_0 {
VertexShader = compile vs_4_0_level_9_1 VSGeneral9_1();
PixelShader = compile ps_4_0_level_9_1 PSVegetation();
}
}
technique VegetationLevel9_3 {
pass Pass_0 {
VertexShader = compile vs_4_0_level_9_3 VSGeneral9_3();
PixelShader = compile ps_4_0_level_9_3 PSVegetation();
}
}
technique TerrainLevel9_1 {
pass Pass_0 {
VertexShader = compile vs_4_0_level_9_1 VSTerrain9_1();
PixelShader = compile ps_4_0_level_9_1 PSTerrain9_1();
}
}
technique TerrainLevel9_3 {
pass Pass_0 {
VertexShader = compile vs_4_0_level_9_3 VSTerrain9_3();
PixelShader = compile ps_4_0_level_9_3 PSTerrain9_3();
}
}
technique DarkShadeLevel9_1 {
pass Pass_0 {
VertexShader = compile vs_4_0_level_9_1 VSGeneral9_1();
PixelShader = compile ps_4_0_level_9_1 PSDarkShade();
}
}
technique DarkShadeLevel9_3 {
pass Pass_0 {
VertexShader = compile vs_4_0_level_9_3 VSGeneral9_3();
PixelShader = compile ps_4_0_level_9_3 PSDarkShade();
}
}
technique HalfBrightLevel9_1 {
pass Pass_0 {
VertexShader = compile vs_4_0_level_9_1 VSGeneral9_1();
PixelShader = compile ps_4_0_level_9_1 PSHalfBright();
}
}
technique HalfBrightLevel9_3 {
pass Pass_0 {
VertexShader = compile vs_4_0_level_9_3 VSGeneral9_3();
PixelShader = compile ps_4_0_level_9_3 PSHalfBright();
}
}
technique FullBrightLevel9_1 {
pass Pass_0 {
VertexShader = compile vs_4_0_level_9_1 VSGeneral9_1();
PixelShader = compile ps_4_0_level_9_1 PSFullBright();
}
}
technique FullBrightLevel9_3 {
pass Pass_0 {
VertexShader = compile vs_4_0_level_9_3 VSGeneral9_3();
PixelShader = compile ps_4_0_level_9_3 PSFullBright();
}
}
technique SignalLight {
pass Pass_0 {
VertexShader = compile vs_4_0_level_9_1 VSSignalLight();
PixelShader = compile ps_4_0_level_9_1 PSSignalLight();
}
}
technique SignalLightGlow {
pass Pass_0 {
VertexShader = compile vs_4_0_level_9_1 VSSignalLightGlow();
PixelShader = compile ps_4_0_level_9_1 PSSignalLight();
}
}