2 // Note:: All channels marked with an ** are currently not filled out by the engine.
5 // ____________________________________________________________________________________________
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)
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)
22 uniform int cmdl_shadows_enable; // Commandline switch --ao
24 uniform int cmdl_ao_enable; // Commandline switch --shadows
25 uniform int cmdl_ao_size;
27 uniform int cmdl_outline_enable;
28 uniform int cmdl_outline_size;
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);
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);
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)
47 uniform sampler2D tex_objectives; // Objectives
48 // R: Objectives (0 or 1)
49 // G: Buzones (0 or 1)
51 // A: Buyzones & Bombsites (mask 0-1)
53 uniform sampler2D tex_props; // Props
54 // **R: Height (0-1 normalized)
57 // **A: Props (0 or 1)
59 uniform sampler2D tex_gradient; // Gradient input
60 // RGBA: 256x1 image defining a gradient
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)
67 // ____________________________________________________________________________________________
68 // --------------------------------------- Blend modes ----------------------------------------
70 vec3 lerp(vec3 a, vec3 b, float w)
75 vec4 blend_normal(vec4 a, vec4 b, float s)
77 return vec4(lerp(a.rgb, b.rgb, b.a * s), a.a + (b.a * s));
80 vec4 blend_add(vec4 a, vec4 b, float s)
82 return vec4(a.rgb + (b.rgb * s), a.a);
85 // ------------------------------------------ maths -------------------------------------------
86 float remap(float value, float low1, float high1, float low2, float high2)
88 return low2 + (value - low1) * (high2 - low2) / (high1 - low1);
91 // ---------------------------------------- transforms ----------------------------------------
92 vec2 worlspaceToScreen(vec3 worldCoord)
95 remap(worldCoord.x, bounds_NWU.x, bounds_SEL.x, 0, 1),
96 remap(worldCoord.y, bounds_SEL.y, bounds_NWU.y, 0, 1));
99 vec3 screenSpaceToWorld(vec2 screenCoord, float heightSample)
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));
107 float screenHeightToWorld(float screenHeight)
109 return remap(screenHeight, 0, 1, bounds_SEL.z, bounds_NWU.z);
112 // -------------------------------------- sample helpers --------------------------------------
114 vec4 sample_gradient(float height)
116 return vec4(texture(tex_gradient, vec2(height, 0)));
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; }
123 float get_height(vec4 sample_playspace) { return sample_playspace.r; }
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)
130 vec2 pixel_size = 1.0 / vec2(textureSize(sampler, 0));
133 int sample_double = sample_size * 2;
136 for(int x = 0; x <= sample_double; x++){
137 for(int y = 0; y <= sample_double; y++){
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];
144 sT /= (sample_double * sample_double);
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)
152 vec2 pixel_size = 1.0 / vec2(textureSize(sampler, 0));
155 int sample_double = sample_size * 2;
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];
166 return max(min(sT, 1) - texture(sampler, TexCoords)[channelID], 0);
169 // Given a height map, return a shadow map for this sample
170 float trace_shadow(sampler2D heightSampler, int channelID)
172 int traceCount = 1024;
174 vec3 angleV = vec3(-0.5, 1, 1);
176 vec3 sampleWorldCoord = screenSpaceToWorld(TexCoords, texture(heightSampler, TexCoords).r);
180 for(int i = 0; i < traceCount; i++)
182 vec3 traceOffset = angleV * i;
183 vec3 stepSampleLoc = sampleWorldCoord + traceOffset;
184 vec2 uvSampleLoc = worlspaceToScreen(stepSampleLoc);
185 float stepSampleHeight = screenHeightToWorld(texture(heightSampler, uvSampleLoc).r);
187 if(stepSampleHeight-sampleWorldCoord.z > traceOffset.z)
193 return clamp(sD, 0, 1);
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)
200 vec2 pixel_size = 1.0 / vec2(textureSize(sampler, 0));
203 int sample_double = sample_size * 2;
205 float thisHeight = texture(sampler, TexCoords)[channelID];
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);
215 sT /= (sample_double * sample_double);
222 // ____________________________________________________________________________________________
223 // ( Write all your shader code & functions here )
227 vec4 sBackground = vec4(texture(tex_background, TexCoords));
228 vec4 sPlayspace = vec4(texture(tex_playspace, TexCoords));
229 vec4 sObjectives = vec4(texture(tex_objectives, TexCoords));
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
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
239 if(cmdl_outline_enable == 1) final = blend_normal(final, outline_color, kernel_filter_outline(tex_playspace, 3, cmdl_outline_size)); // Outline
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));
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));
250 // Return the final output color