2.0
[tar-legacy.git] / MCDV / shaders / ss_comp_main.fso
1 #version 330 core
2 // Note:: All channels marked with an ** are currently not filled out by the engine.
3
4 // OPENGL
5 // ____________________________________________________________________________________________
6 in vec2 TexCoords;
7 out vec4 FragColor;
8
9 // UNIFORMS
10 // Vector Information _________________________________________________________________________
11 // ( A bunch of vectors that give you the location of different entities )
12 uniform vec3 bounds_NWU; // North-West-Upper coordinate of the playspace (worldspace)
13 uniform vec3 bounds_SEL; // South-East-Lower coordinate of the playspace (worldspace)
14 uniform vec2 bounds_NWU_SS; // **North-West coordinate of the playspace (UV Screenspace)
15 uniform vec2 bounds_SEL_SS; // **South-East coordinate of the playspace (UV Screenspace)
16
17 uniform vec2 pos_spawn_ct; // **Location of the CT Spawn (UV Screenspace)
18 uniform vec2 pos_spawn_t; // **Location of the T Spawn (UV Screenspace)
19 uniform vec2 bombsite_a; // **Location of bomsite A (UV Screenspace)
20 uniform vec2 bombsite_b; // **Location of bombsite B (UV Screenspace)
21
22 uniform int cmdl_shadows_enable; // Commandline switch --ao
23
24 uniform int cmdl_ao_enable; // Commandline switch --shadows
25 uniform int cmdl_ao_size;
26
27 uniform int cmdl_outline_enable;
28 uniform int cmdl_outline_size;
29
30 uniform vec4 outline_color;// = vec4(0.8, 0.8, 0.8, 0.6);
31 uniform vec4 ao_color;// = vec4(0.0, 0.0, 0.0, 1.0);
32
33 uniform vec4 buyzone_color;// = vec4(0.180, 0.828, 0.225, 0.667);
34 uniform vec4 objective_color;// = vec4(0.770, 0.295, 0.171, 1.000);
35 uniform vec4 cover_color;// = vec4(0.700, 0.700, 0.700, 1.000);
36
37 // SAMPLER UNIFORMS
38 // Image Inputs _______________________________________________________________________________
39 // ( Standard generated maps from the engine )
40 uniform sampler2D tex_background; // Background texture
41 uniform sampler2D tex_playspace; // Playspace
42 // R: Height (Regular)
43 // G: Height (Reverse rendering order)
44 // **B: Baked Lighting
45 // A: Playable Space (0 or 1)
46
47 uniform sampler2D tex_objectives; // Objectives
48 // R: Objectives (0 or 1)
49 // G: Buzones (0 or 1)
50 // B: none
51 // A: Buyzones & Bombsites (mask 0-1)
52
53 uniform sampler2D tex_props; // Props
54 // **R: Height (0-1 normalized)
55 // **G: none
56 // **B: none
57 // **A: Props (0 or 1)
58
59 uniform sampler2D tex_gradient; // Gradient input
60 // RGBA: 256x1 image defining a gradient
61
62 uniform sampler2D texture0; // Custom Image input 3 (**RGBA)
63 uniform sampler2D texture1; // Custom Image input 4 (**RGBA)
64 uniform sampler2D texture2; // Custom Image input 5 (**RGBA)
65
66 // SHADER HELPERS
67 // ____________________________________________________________________________________________
68 // --------------------------------------- Blend modes ----------------------------------------
69
70 vec3 lerp(vec3 a, vec3 b, float w)
71 {
72 return a + w*(b-a);
73 }
74
75 vec4 blend_normal(vec4 a, vec4 b, float s)
76 {
77 return vec4(lerp(a.rgb, b.rgb, b.a * s), a.a + (b.a * s));
78 }
79
80 vec4 blend_add(vec4 a, vec4 b, float s)
81 {
82 return vec4(a.rgb + (b.rgb * s), a.a);
83 }
84
85 // ------------------------------------------ maths -------------------------------------------
86 float remap(float value, float low1, float high1, float low2, float high2)
87 {
88 return low2 + (value - low1) * (high2 - low2) / (high1 - low1);
89 }
90
91 // ---------------------------------------- transforms ----------------------------------------
92 vec2 worlspaceToScreen(vec3 worldCoord)
93 {
94 return vec2(
95 remap(worldCoord.x, bounds_NWU.x, bounds_SEL.x, 0, 1),
96 remap(worldCoord.y, bounds_SEL.y, bounds_NWU.y, 0, 1));
97 }
98
99 vec3 screenSpaceToWorld(vec2 screenCoord, float heightSample)
100 {
101 return vec3(
102 remap(screenCoord.x, 0, 1, bounds_NWU.x, bounds_SEL.x),
103 remap(screenCoord.y, 0, 1, bounds_SEL.y, bounds_NWU.y),
104 remap(heightSample, 0, 1, bounds_SEL.z, bounds_NWU.z));
105 }
106
107 float screenHeightToWorld(float screenHeight)
108 {
109 return remap(screenHeight, 0, 1, bounds_SEL.z, bounds_NWU.z);
110 }
111
112 // -------------------------------------- sample helpers --------------------------------------
113
114 vec4 sample_gradient(float height)
115 {
116 return vec4(texture(tex_gradient, vec2(height, 0)));
117 }
118
119 float get_playspace(vec4 sample_playspace) { return sample_playspace.a; }
120 float get_playspace_height(vec4 sample_playspace) { return sample_playspace.a * sample_playspace.r; }
121 float get_playspace_inverse_height(vec4 sample_playspace) { return sample_playspace.a * sample_playspace.g; }
122
123 float get_height(vec4 sample_playspace) { return sample_playspace.r; }
124
125
126 // ---------------------------------- kernel / trace filters ----------------------------------
127 // Given an 0-1 mask, return a 'glow value'
128 float kernel_filter_glow(sampler2D sampler, int channelID, int sample_size, int inverse)
129 {
130 vec2 pixel_size = 1.0 / vec2(textureSize(sampler, 0));
131
132 float sT = 0;
133 int sample_double = sample_size * 2;
134
135 // Process kernel
136 for(int x = 0; x <= sample_double; x++){
137 for(int y = 0; y <= sample_double; y++){
138 if(inverse == 0)
139 sT += texture(sampler, TexCoords + vec2((-sample_size + x) * pixel_size.x, (-sample_size + y) * pixel_size.y))[channelID];
140 else sT += 1 - texture(sampler, TexCoords + vec2((-sample_size + x) * pixel_size.x, (-sample_size + y) * pixel_size.y))[channelID];
141 }
142 }
143
144 sT /= (sample_double * sample_double);
145
146 return sT;
147 }
148
149 // Given a 0-1 mask, return an outline drawn around that mask
150 float kernel_filter_outline(sampler2D sampler, int channelID, int sample_size)
151 {
152 vec2 pixel_size = 1.0 / vec2(textureSize(sampler, 0));
153
154 float sT = 0;
155 int sample_double = sample_size * 2;
156
157 // Process kernel
158 for(int x = 0; x <= sample_double; x++){
159 for(int y = 0; y <= sample_double; y++){
160 sT += //texture(sampler, TexCoords + vec2((-sample_size + x) * pixel_size.x, (-sample_size + y) * pixel_size.y))[channelID];
161 (sample_size - min(length(vec2(-sample_size + x, -sample_size + y)), sample_size)) *
162 texture(sampler, TexCoords + vec2((-sample_size + x) * pixel_size.x, (-sample_size + y) * pixel_size.y))[channelID];
163 }
164 }
165
166 return max(min(sT, 1) - texture(sampler, TexCoords)[channelID], 0);
167 }
168
169 // Given a height map, return a shadow map for this sample
170 float trace_shadow(sampler2D heightSampler, int channelID)
171 {
172 int traceCount = 1024;
173
174 vec3 angleV = vec3(-0.5, 1, 1);
175
176 vec3 sampleWorldCoord = screenSpaceToWorld(TexCoords, texture(heightSampler, TexCoords).r);
177
178 float sD = 0;
179
180 for(int i = 0; i < traceCount; i++)
181 {
182 vec3 traceOffset = angleV * i;
183 vec3 stepSampleLoc = sampleWorldCoord + traceOffset;
184 vec2 uvSampleLoc = worlspaceToScreen(stepSampleLoc);
185 float stepSampleHeight = screenHeightToWorld(texture(heightSampler, uvSampleLoc).r);
186
187 if(stepSampleHeight-sampleWorldCoord.z > traceOffset.z)
188 {
189 sD += 1;
190 }
191 }
192
193 return clamp(sD, 0, 1);
194 }
195
196 // Given a height map, return an ambient occlusion term for this sample
197 // This is a wip, expect kinda shitty results :)
198 float kernel_ao_basic(sampler2D sampler, int channelID, int sample_size)
199 {
200 vec2 pixel_size = 1.0 / vec2(textureSize(sampler, 0));
201
202 float sT = 0;
203 int sample_double = sample_size * 2;
204
205 float thisHeight = texture(sampler, TexCoords)[channelID];
206
207 // Process kernel
208 for(int x = 0; x <= sample_double; x++){
209 for(int y = 0; y <= sample_double; y++){
210 float dif = texture(sampler, TexCoords + vec2((-sample_size + x) * pixel_size.x, (-sample_size + y) * pixel_size.y))[channelID] - thisHeight;
211 sT += clamp(dif, 0, 0.04);
212 }
213 }
214
215 sT /= (sample_double * sample_double);
216 sT *= 16;
217
218 return sT;
219 }
220
221 // SHADER PROGRAM
222 // ____________________________________________________________________________________________
223 // ( Write all your shader code & functions here )
224
225 void main()
226 {
227 vec4 sBackground = vec4(texture(tex_background, TexCoords));
228 vec4 sPlayspace = vec4(texture(tex_playspace, TexCoords));
229 vec4 sObjectives = vec4(texture(tex_objectives, TexCoords));
230
231 vec4 final = sBackground;
232 final = blend_normal(final, vec4(0,0,0,1), kernel_filter_glow(tex_playspace, 3, 16, 0)); // Drop shadow
233 final = blend_normal(final, sample_gradient(get_playspace_height(sPlayspace)), get_playspace(sPlayspace)); // Playspace
234 final = blend_normal(final, cover_color, sPlayspace.b); // Cover
235
236 if(cmdl_shadows_enable == 1) final = blend_normal(final, vec4(0,0,0,1), trace_shadow(tex_playspace, 0) * 0.2); // Shadows
237 if(cmdl_ao_enable == 1) final = blend_normal(final, ao_color, kernel_ao_basic(tex_playspace, 0, cmdl_ao_size) * 0.9 * sPlayspace.a); // AO
238
239 if(cmdl_outline_enable == 1) final = blend_normal(final, outline_color, kernel_filter_outline(tex_playspace, 3, cmdl_outline_size)); // Outline
240
241 final = blend_normal(final, objective_color, // Objectives
242 (kernel_filter_glow(tex_objectives, 0, 16, 1) * sObjectives.r) +
243 kernel_filter_outline(tex_objectives, 0, 2));
244
245 final = blend_normal(final, buyzone_color, // Buyzones
246 (kernel_filter_glow(tex_objectives, 1, 16, 1) * sObjectives.g) +
247 kernel_filter_outline(tex_objectives, 1, 2));
248
249
250 // Return the final output color
251 FragColor = final;
252 }