alot of changes; geometry highlighting is broken; but you can control console colors...
[dd2d.git] / data / shaders / srlight_geom.frag
blob90e53e70040a7dfc4c308e2f479ea25d25ef01a9
1 /* DooM2D: Midnight on the Firing Line
2  * coded by Ketmar // Invisible Vector <ketmar@ketmar.no-ip.org>
3  * Understanding is not required. Only obedience.
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17  */
18 // this shader will light level geometry
19 #version 130
21 #define PI 3.1415926
23 // alpha threshold for our occlusion map
24 #define THRESHOLD  (0.75)
26 #define SEARCH_RADIUS  (4)
27 #define MIN_ALPHA  (0.04)
29 uniform sampler2D texLMap; // light texture of lightTexSize
30 uniform sampler2D texBg; // background
31 uniform sampler2D texOccFull; // occluders
32 uniform sampler2D texOccSmall; // occluders, small map
33 uniform vec2 lightTexSize; // x: lightSize; y: size of this texture
34 uniform vec2 mapPixSize;
35 uniform vec4 lightColor;
36 uniform vec2 lightPos;
39 bool lightAtTile (vec2 ltpos, float pixelStep) {
40   if (ltpos.x < 0 || ltpos.y < 0 || ltpos.x >= 1.0 || ltpos.y >= 1.0) return false;
41   float lx = ltpos.x;
42   for (int dy = 8; dy > 0; --dy) {
43     for (int dx = 8; dx > 0; --dx) {
44       if (texture2D(texLMap, ltpos, 0).a > MIN_ALPHA) return true;
45       ltpos.x += pixelStep;
46     }
47     ltpos = vec2(lx, ltpos.y+pixelStep);
48   }
49   return false;
53 //gl_FragCoord: in background
55 void main (void) {
56   // light is y-mirrored
57   vec2 ourpos = vec2(gl_FragCoord.x, mapPixSize.y-gl_FragCoord.y);
59   ivec2 ocxy = ivec2(int(ourpos.x), int(ourpos.y));
60   // empty space?
61   if (texelFetch(texOccFull, ocxy, 0).a <= THRESHOLD) {
62     discard;
63     //gl_FragColor = vec4(1.0, 0.0, 0.0, 0.5);
64     return;
65   }
67   // check adjacent tiles
68   bool hit = false;
69   {
70 #if 0
71     vec2 ltpos = gl_TexCoord[0].xy; // in light texture (texLMap)
72     float pixelStep = 1.0/lightTexSize.y; // in light texture
73     int move = ocxy.x&0x07;
74     ltpos.x -= pixelStep*move;
75     move = int(gl_FragCoord.y)&0x07;
76     ltpos.y -= pixelStep*move;
77     // check adjacent tiles
78     ltpos -= pixelStep*8;
79     float savedx = ltpos.x;
80     for (int dy = -1; dy < 2 && !hit; ++dy) {
81       for (int dx = -1; dx < 2 && !hit; ++dx) {
82         if (dx != 0 || dy != 0) hit = lightAtTile(ltpos, pixelStep);
83         ltpos.x += pixelStep*8;
84       }
85       ltpos = vec2(savedx, ltpos.y+pixelStep*8);
86     }
87 #else
88     /*
89     for (int dy = 8; dy > 0; --dy) {
90       if (texture2D(texLMap, ltpos, 0).a > MIN_ALPHA) { hit = true; break; }
91       ltpos.y -= pixelStep;
92     }
93     */
94     //gl_FragColor = vec4(gl_TexCoord[0].y, 0, 0, 1);
95     //return;
96     /*
97     ocxy.x = ocxy.x&~7;
98     ocxy.y = ocxy.y&~7;
99     */
100     float tlsz = textureSize(texLMap, 0).y;
101     vec2 ltpos = gl_TexCoord[0].xy; // in light texture (texLMap)
102     float pixelStep = 1.0/tlsz; // in light texture
103     //ltpos.y += pixelStep;
104     //hit = (texture2D(texLMap, ltpos/tlsz, 0).a > MIN_ALPHA);
105     hit = (
106       texture2D(texLMap, vec2(ltpos.x-pixelStep, ltpos.y-pixelStep), 0).a > MIN_ALPHA ||
107       texture2D(texLMap, vec2(ltpos.x          , ltpos.y-pixelStep), 0).a > MIN_ALPHA ||
108       texture2D(texLMap, vec2(ltpos.x+pixelStep, ltpos.y-pixelStep), 0).a > MIN_ALPHA ||
109       texture2D(texLMap, vec2(ltpos.x-pixelStep, ltpos.y          ), 0).a > MIN_ALPHA ||
110       texture2D(texLMap, vec2(ltpos.x+pixelStep, ltpos.y          ), 0).a > MIN_ALPHA ||
111       texture2D(texLMap, vec2(ltpos.x-pixelStep, ltpos.y+pixelStep), 0).a > MIN_ALPHA ||
112       texture2D(texLMap, vec2(ltpos.x          , ltpos.y+pixelStep), 0).a > MIN_ALPHA ||
113       texture2D(texLMap, vec2(ltpos.x+pixelStep, ltpos.y+pixelStep), 0).a > MIN_ALPHA ||
114       false
115       );
116 #endif
117   }
119   if (hit) {
120     vec4 color;
121     // background
122     //vec2 btxy = gl_FragCoord.xy/mapPixSize;
123     //vec4 bcolor = texture2D(texBg, btxy);
124     vec4 bcolor = texelFetch(texBg, ivec2(int(gl_FragCoord.x), int(gl_FragCoord.y)), 0);
125     // distance from this point to light origin
126     float lit = clamp(1.0-(distance(ourpos, lightPos)/(lightTexSize.x/2.0)), 0.0, 1.0);
127     lit = smoothstep(0.1, 1.0, lit);
128     if (lightColor.a == 0.0) {
129       color = bcolor*vec4(vec3(1.0), lit);
130     } else {
131       color = lightColor*lit;
132       color += bcolor*lit;
133       color.a = lit/2.0;
134     }
135     gl_FragColor = color;
136     //gl_FragColor = bcolor;
137   } else {
138     discard;
139     //gl_FragColor = vec4(0.0, 0.0, 1.0, 0.5);
140   }
142 #if 0
143   // occluder hit
144   // first, we should check if there is no other occluders in +x, +y, and +x+y directions
145   ivec2 a8 = ocxy/8;
146   //ivec2 ldxy = ivec2(int(sign(lightPos.x-gl_FragCoord.x)), int(sign(gl_FragCoord.y-lightPos.y)));
147   ivec2 ltposd8 = ivec2(int(lightPos.x), int(lightPos.y))/8;
148   //ivec2 ltposd8 = ocxy/8;
149   ivec2 ldxy = ivec2(sign(ltposd8.x-a8.x), sign(ltposd8.y-a8.y));
150 #if 0
151   if (ldxy.x == 0 && ldxy.y == 0) { discard; return; }
152   if (ldxy.x != 0 && ldxy.y != 0) {
153     // both directions
154     if (/*texelFetch(texOccSmall, ivec2(a8.x+ldxy.x, a8.y), 0).a > THRESHOLD &&
155         texelFetch(texOccSmall, ivec2(a8.x, a8.y+ldxy.y), 0).a > THRESHOLD &&*/
156         texelFetch(texOccSmall, a8+ldxy, 0).a > THRESHOLD) { discard; return; }
157   } else {
158     // only horizontal or only vertical
159     if (texelFetch(texOccSmall, a8+ldxy, 0).a > THRESHOLD) { discard; return; }
160   }
161 #endif
162   // ok, it's not blocked
164   // check for light in +x, +y, and +x+y directions
165   vec2 ltpos = gl_TexCoord[0].xy*textureSize(texLMap, 0).y/*lightTexSize.y*/; // in light texture (texLMap)
166   ivec2 iltpos = ivec2(int(ltpos.x), int(ltpos.y));
168   bool hit = false;
169   float litlt = 0;
170   for (int f = 1; f > 0; --f) {
171     float ar = texelFetch(texLMap, iltpos, 0).a;
172     ar = max(ar, texelFetch(texLMap, ivec2(iltpos.x+ldxy.x, iltpos.y), 0).a);
173     ar = max(ar, texelFetch(texLMap, ivec2(iltpos.x, iltpos.y+ldxy.x), 0).a);
174     ar = max(ar, texelFetch(texLMap, ivec2(iltpos.x+ldxy.x, iltpos.y+ldxy.x), 0).a);
175     if (ar > MIN_ALPHA) {
176       hit = true;
177       ar *= 1.5;
178       litlt = max(min(ar, 1.0), 0.0);
179       break;
180     }
181     iltpos += ldxy;
182   }
184   if (hit) {
185     vec4 color;
186     // background
187     //vec2 btxy = gl_FragCoord.xy/mapPixSize;
188     //vec4 bcolor = texture2D(texBg, btxy);
189     vec4 bcolor = texelFetch(texBg, ivec2(int(gl_FragCoord.x), int(gl_FragCoord.y)), 0);
190     // distance from this point to light origin
191     float lit = clamp(1.0-(distance(ourpos, lightPos)/(lightTexSize.x/2.0)), 0.0, 1.0);
192     lit = smoothstep(0.1, 1.0, lit);
193     lit = litlt;
194     if (lightColor.a == 0.0) {
195       color = bcolor*vec4(vec3(1.0), lit);
196     } else {
197       color = lightColor*lit;
198       color += bcolor*lit;
199       color.a = lit/2.0;
200     }
201     //gl_FragColor = color;
202     gl_FragColor = bcolor;
203   } else {
204     discard;
205   }
206 #endif