~ubuntu-branches/debian/stretch/assaultcube-data/stretch

« back to all changes in this revision

Viewing changes to source/src/shadow.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Gonéri Le Bouder, Ansgar Burchardt, Gonéri Le Bouder
  • Date: 2010-04-02 23:37:55 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20100402233755-kf74fxwlu634o6vg
Tags: 1.0.4+repack1-1
[ Ansgar Burchardt ]
* debian/control: fix typo in short description

[ Gonéri Le Bouder ]
* Upgrade to 1.0.4
* bump standards-version to 3.8.4
* Add Depends: ${misc:Depends} just to avoid a lintian warning
* Add a debian/source/format file for the same reason

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// shadow.cpp: stencil shadow rendering
 
2
 
 
3
#include "pch.h"
 
4
#include "cube.h"
 
5
 
 
6
VARP(stencilshadow, 0, 40, 100);
 
7
 
 
8
int stenciling = 0;
 
9
 
 
10
VAR(shadowclip, 0, 1, 1);
 
11
VAR(shadowtile, 0, 1, 1);
 
12
VAR(dbgtiles, 0, 0, 1);
 
13
VAR(shadowcasters, 1, 0, 0);
 
14
 
 
15
#define SHADOWROWS 64
 
16
#define SHADOWCOLUMNS 32
 
17
#define SHADOWCOLUMNMASK (0xFFFFFFFFU>>(32-SHADOWCOLUMNS))
 
18
uint shadowtiles[SHADOWROWS+1];
 
19
float shadowx1 = 1, shadowy1 = 1, shadowx2 = -1, shadowy2 = -1;
 
20
 
 
21
static void extrudeshadowtiles(int x1, int y1, int x2, int y2, int x3, int y3)
 
22
{
 
23
    if(y1 > y2) { swap(x1, x2); swap(y1, y2); }
 
24
    if(y2 > y3) { swap(x2, x3); swap(y2, y3); }
 
25
    if(y1 > y2) { swap(x1, x2); swap(y1, y2); }
 
26
 
 
27
    if(y3 < 0 || y1 >= SHADOWROWS) return;
 
28
 
 
29
    int lx = x1, rx = x1,
 
30
        fracl = 0, fracr = 0,
 
31
        dlx, dly, drx, dry;
 
32
    if(x2 <= x3) { dlx = x2; dly = y2; drx = x3; dry = y3; }
 
33
    else { dlx = x3; dly = y3; drx = x2; dry = y2; }
 
34
    dlx -= x1; dly -= y1;
 
35
    drx -= x1; dry -= y1;
 
36
    int ldir = 1, rdir = 1;
 
37
    if(dlx < 0)
 
38
    {
 
39
        ldir = -1;
 
40
        dlx = -dlx;
 
41
    }
 
42
    if(drx < 0)
 
43
    {
 
44
        rdir = -1;
 
45
        drx = -drx;
 
46
    }
 
47
 
 
48
    int cy = y1;
 
49
    y2 = min(y2, SHADOWROWS);
 
50
    if(cy < 0 && y2 > cy)
 
51
    {
 
52
        int dy = min(y2, 0) - cy;
 
53
        cy += dy;
 
54
        fracl += dy*dlx;
 
55
        lx += ldir*(fracl/dly);
 
56
        fracl %= dly;
 
57
        fracr += dy*drx;
 
58
        rx += rdir*(fracr/dry);
 
59
        fracr %= dry;
 
60
    }
 
61
 
 
62
    for(; cy < y2; cy++)
 
63
    {
 
64
        int cx1 = lx, cx2 = rx;
 
65
        fracl += dlx;
 
66
        while(fracl >= dly) { lx += ldir; if(ldir < 0) cx1 = lx; fracl -= dly; }
 
67
        fracr += drx;
 
68
        while(fracr >= dry) { rx += rdir; if(rdir > 0) cx2 = rx; fracr -= dry; }
 
69
        if(cx1 < SHADOWCOLUMNS && cx2 >= 0) shadowtiles[cy] |= (SHADOWCOLUMNMASK>>(SHADOWCOLUMNS - (min(cx2, SHADOWCOLUMNS-1)+1))) & (SHADOWCOLUMNMASK<<max(cx1, 0));
 
70
    }
 
71
 
 
72
    if(cy >= SHADOWROWS) return;
 
73
 
 
74
    if(x2 < x3 || y1 == cy)
 
75
    {
 
76
        if(x2 < lx) lx = x2;
 
77
        dlx = x3 - lx; dly = y3 - cy;
 
78
        ldir = 1;
 
79
        if(dlx < 0)
 
80
        {
 
81
            ldir = -1;
 
82
            dlx = -dlx;
 
83
        }
 
84
        fracl = 0;
 
85
    }
 
86
    if(x2 > x3 || y1 == cy) 
 
87
    {
 
88
        if(x2 > rx) rx = x2;
 
89
        drx = x3 - rx; dry = y3 - cy;
 
90
        rdir = 1;
 
91
        if(drx < 0)
 
92
        {
 
93
            rdir = -1;
 
94
            drx = -drx;
 
95
        }
 
96
        fracr = 0;
 
97
    }
 
98
 
 
99
    y3 = min(y3, SHADOWROWS);
 
100
    if(cy < 0 && y3 > cy)
 
101
    {
 
102
        int dy = min(y3, 0) - cy;
 
103
        cy += dy;
 
104
        fracl += dy*dlx;
 
105
        lx += ldir*(fracl/dly);
 
106
        fracl %= dly;
 
107
        fracr += dy*drx;
 
108
        rx += rdir*(fracr/dry);
 
109
        fracr %= dry;
 
110
    }
 
111
 
 
112
    for(; cy < y3; cy++)
 
113
    {
 
114
        int cx1 = lx, cx2 = rx;
 
115
        fracl += dlx;
 
116
        while(fracl >= dly) { lx += ldir; if(ldir < 0) cx1 = lx; fracl -= dly; }
 
117
        fracr += drx;
 
118
        while(fracr >= dry) { rx += rdir; if(rdir > 0) cx2 = rx; fracr -= dry; }
 
119
        if(cx1 < SHADOWCOLUMNS && cx2 >= 0) shadowtiles[cy] |= (SHADOWCOLUMNMASK>>(SHADOWCOLUMNS - (min(cx2, SHADOWCOLUMNS-1)+1))) & (SHADOWCOLUMNMASK<<max(cx1, 0));
 
120
    }
 
121
 
 
122
    if(cy < SHADOWROWS)
 
123
    {
 
124
        int cx1 = lx, cx2 = rx;
 
125
        if(dly)
 
126
        {
 
127
            fracl += dlx;
 
128
            while(fracl >= dly) { lx += ldir; if(ldir < 0) cx1 = lx; fracl -= dly; }
 
129
        }
 
130
        if(dry)
 
131
        {
 
132
            fracr += drx;
 
133
            while(fracr >= dry) { rx += rdir; if(rdir > 0) cx2 = rx; fracr -= dry; }
 
134
        }
 
135
        if(cx1 < SHADOWCOLUMNS && cx2 >= 0) shadowtiles[cy] |= (SHADOWCOLUMNMASK>>(SHADOWCOLUMNS - (min(cx2, SHADOWCOLUMNS-1)+1))) & (SHADOWCOLUMNMASK<<max(cx1, 0));
 
136
    }
 
137
}
 
138
 
 
139
static void addshadowtiles(float x1, float y1, float x2, float y2)
 
140
{
 
141
    shadowx1 = min(shadowx1, x1);
 
142
    shadowy1 = min(shadowy1, y1);
 
143
    shadowx2 = max(shadowx2, x2);
 
144
    shadowy2 = max(shadowy2, y2);
 
145
 
 
146
    int tx1 = clamp(int(floor((y1 + 1)/2 * SHADOWCOLUMNS)), 0, SHADOWCOLUMNS - 1),
 
147
        ty1 = clamp(int(floor((x1 + 1)/2 * SHADOWROWS)), 0, SHADOWROWS - 1),
 
148
        tx2 = clamp(int(floor((y2 + 1)/2 * SHADOWCOLUMNS)), 0, SHADOWCOLUMNS - 1),
 
149
        ty2 = clamp(int(floor((x2 + 1)/2 * SHADOWROWS)), 0, SHADOWROWS - 1);
 
150
 
 
151
    uint mask = (SHADOWCOLUMNMASK>>(SHADOWCOLUMNS - (tx2+1))) & (SHADOWCOLUMNMASK<<tx1);
 
152
    for(int y = ty1; y <= ty2; y++) shadowtiles[y] |= mask;
 
153
}
 
154
 
 
155
bool addshadowbox(const vec &bbmin, const vec &bbmax, const vec &extrude, const glmatrixf &mat)
 
156
{
 
157
    vec4 v[8];
 
158
    float sx1 = 1e16f, sy1 = 1e16f, sx2 = -1e16f, sy2 = -1e16f;
 
159
    int front = 0;
 
160
    loopi(8)
 
161
    {
 
162
        vec4 &p = v[i];
 
163
        mat.transform(vec(i&1 ? bbmax.x : bbmin.x, i&2 ? bbmax.y : bbmin.y, i&4 ? bbmax.z : bbmin.z), p); 
 
164
        if(p.z >= 0)
 
165
        {
 
166
            float x = p.x / p.w, y = p.y / p.w;
 
167
            sx1 = min(sx1, x);
 
168
            sy1 = min(sy1, y);
 
169
            sx2 = max(sx2, x);
 
170
            sy2 = max(sy2, y);
 
171
            front++;
 
172
        }
 
173
    }
 
174
    vec4 ev;
 
175
    mat.transform(extrude, ev);
 
176
    if(ev.z < 0 && !front) return false;
 
177
    if(front < 8 || ev.z < 0) loopi(8)
 
178
    {
 
179
        const vec4 &p = v[i];
 
180
        if(p.z >= 0) 
 
181
        {
 
182
            if(ev.z >= 0) continue;
 
183
            float t = ev.z/(ev.z - p.z),
 
184
                  w = ev.w + t*(p.w - ev.w),
 
185
                  x = (ev.x + t*(p.x - ev.x))/w,
 
186
                  y = (ev.y + t*(p.y - ev.y))/w;
 
187
            sx1 = min(sx1, x);
 
188
            sy1 = min(sy1, y);
 
189
            sx2 = max(sx2, x);
 
190
            sy2 = max(sy2, y);
 
191
            continue;
 
192
        }
 
193
        loopj(3)
 
194
        {
 
195
            const vec4 &o = v[i^(1<<j)];
 
196
            if(o.z < 0) continue;
 
197
            float t = p.z/(p.z - o.z),
 
198
                  w = p.w + t*(o.w - p.w),
 
199
                  x = (p.x + t*(o.x - p.x))/w,
 
200
                  y = (p.y + t*(o.y - p.y))/w;
 
201
            sx1 = min(sx1, x);
 
202
            sy1 = min(sy1, y);
 
203
            sx2 = max(sx2, x);
 
204
            sy2 = max(sy2, y);
 
205
        }
 
206
        if(ev.z < 0) continue;
 
207
        float t = p.z/(p.z - ev.z),
 
208
              w = p.w + t*(ev.w - p.w),
 
209
              x = (p.x + t*(ev.x - p.x))/w,
 
210
              y = (p.y + t*(ev.y - p.y))/w;
 
211
        sx1 = min(sx1, x);
 
212
        sy1 = min(sy1, y);
 
213
        sx2 = max(sx2, x);
 
214
        sy2 = max(sy2, y);
 
215
    }
 
216
    if(ev.z >= 0)
 
217
    {
 
218
        float x = ev.x/ev.w, y = ev.y/ev.w;
 
219
        if((sx1 >= 1 && x >= 1) || (sy1 >= 1 && y >= 1) || (sx2 <= -1 && x <= -1) || (sy2 <= -1 && y <= -1)) return false;
 
220
        int tx = int(floor(SHADOWCOLUMNS * (y + 1) / 2)), ty = int(floor(SHADOWROWS * (x + 1) / 2)),
 
221
            tx1 = int(floor(SHADOWCOLUMNS * (sy1 + 1) / 2)), ty1 = int(floor(SHADOWROWS * (sx1 + 1) / 2)),
 
222
            tx2 = int(floor(SHADOWCOLUMNS * (sy2 + 1) / 2)), ty2 = int(floor(SHADOWROWS * (sx2 + 1) / 2));
 
223
        if(tx < tx1)
 
224
        {
 
225
            if(ty < ty1) { swap(ty1, ty2); tx1--; ty1--; }
 
226
            else if(ty > ty2) { tx1--; ty1++; }
 
227
            else { tx2 = tx1; tx1--; tx2--; }
 
228
        }
 
229
        else if(tx > tx2)
 
230
        {
 
231
            if(ty < ty1) { ty1--; tx2++; }
 
232
            else if(ty > ty2) { swap(ty1, ty2); ty1++; tx2++; }
 
233
            else { tx1 = tx2; tx1++; tx2++; }
 
234
        }
 
235
        else
 
236
        {
 
237
            if(ty < ty1) { ty2 = ty1; ty1--; ty2--; }
 
238
            else if(ty > ty2) { ty1 = ty2; ty1++; ty2++; }
 
239
            else goto noextrusion;
 
240
        }
 
241
        extrudeshadowtiles(tx, ty, tx1, ty1, tx2, ty2);
 
242
        shadowx1 = min(x, shadowx1);
 
243
        shadowy1 = min(y, shadowy1);
 
244
        shadowx2 = max(x, shadowx2);
 
245
        shadowy2 = max(y, shadowy2);
 
246
    noextrusion:;
 
247
    }
 
248
    else if(sx1 >= 1 || sy1 >= 1 || sx2 <= -1 || sy2 <= -1) return false;
 
249
    shadowcasters++;
 
250
    addshadowtiles(sx1, sy1, sx2, sy2);
 
251
    return true;
 
252
}
 
253
 
 
254
static void rendershadowtiles()
 
255
{
 
256
    shadowx1 = clamp(shadowx1, -1.0f, 1.0f);
 
257
    shadowy1 = clamp(shadowy1, -1.0f, 1.0f);
 
258
    shadowx2 = clamp(shadowx2, -1.0f, 1.0f);
 
259
    shadowy2 = clamp(shadowy2, -1.0f, 1.0f);
 
260
 
 
261
    if(shadowx1 >= shadowx2 || shadowy1 >= shadowy2) return;
 
262
 
 
263
    float clipx1 = (shadowy1 + 1) / 2,
 
264
          clipy1 = (shadowx1 + 1) / 2,
 
265
          clipx2 = (shadowy2 + 1) / 2,
 
266
          clipy2 = (shadowx2 + 1) / 2;
 
267
    if(!shadowclip)
 
268
    {
 
269
        clipx1 = clipy1 = 0;
 
270
        clipx2 = clipy2 = 1;
 
271
    }
 
272
 
 
273
    if(!shadowtile)
 
274
    {
 
275
        glBegin(GL_QUADS);
 
276
        glVertex2f(clipy1, clipx1);
 
277
        glVertex2f(clipy1, clipx2);
 
278
        glVertex2f(clipy2, clipx2);
 
279
        glVertex2f(clipy2, clipx1);
 
280
        xtraverts += 4;
 
281
        glEnd();
 
282
        return;
 
283
    }
 
284
 
 
285
    glBegin(GL_QUADS);
 
286
    float tw = 1.0f/SHADOWCOLUMNS, th = 1.0f/SHADOWROWS;
 
287
    loop(y, SHADOWROWS+1)
 
288
    {
 
289
        uint mask = shadowtiles[y];
 
290
        int x = 0;
 
291
        while(mask)
 
292
        {
 
293
            while(!(mask&0xFF)) { mask >>= 8; x += 8; }
 
294
            while(!(mask&1)) { mask >>= 1; x++; }
 
295
            int xstart = x;
 
296
            do { mask >>= 1; x++; } while(mask&1);
 
297
            uint strip = (SHADOWCOLUMNMASK>>(SHADOWCOLUMNS - x)) & (SHADOWCOLUMNMASK<<xstart);
 
298
            int yend = y;
 
299
            do { shadowtiles[yend] &= ~strip; yend++; } while((shadowtiles[yend] & strip) == strip);
 
300
            float vx = xstart*tw,
 
301
                  vy = y*th,
 
302
                  vw = (x-xstart)*tw,
 
303
                  vh = (yend-y)*th,
 
304
                  vx1 = max(vx, clipx1),
 
305
                  vy1 = max(vy, clipy1),
 
306
                  vx2 = min(vx+vw, clipx2),
 
307
                  vy2 = min(vy+vh, clipy2);
 
308
            glVertex2f(vy1, vx1);
 
309
            glVertex2f(vy1, vx2);
 
310
            glVertex2f(vy2, vx2);
 
311
            glVertex2f(vy2, vx1);
 
312
            xtraverts += 4;
 
313
        }
 
314
    }
 
315
    glEnd();
 
316
}
 
317
 
 
318
void drawstencilshadows()
 
319
{
 
320
    glDisable(GL_FOG);
 
321
    glEnable(GL_STENCIL_TEST);
 
322
    glDisable(GL_TEXTURE_2D);
 
323
 
 
324
    glDepthMask(GL_FALSE);
 
325
    glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
 
326
 
 
327
    stenciling = 1;
 
328
 
 
329
    shadowcasters = 0;
 
330
    shadowx2 = shadowy2 = -1;
 
331
    shadowx1 = shadowy1 = 1;
 
332
    memset(shadowtiles, 0, sizeof(shadowtiles));
 
333
 
 
334
    if(hasST2 || hasSTS)
 
335
    {
 
336
        glDisable(GL_CULL_FACE);
 
337
 
 
338
        if(hasST2)
 
339
        {
 
340
            glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
 
341
 
 
342
            glActiveStencilFace_(GL_BACK);
 
343
            glStencilFunc(GL_ALWAYS, 0, ~0U);
 
344
            glStencilOp(GL_KEEP, GL_KEEP, hasSTW ? GL_INCR_WRAP_EXT : GL_INCR);
 
345
 
 
346
            glActiveStencilFace_(GL_FRONT);
 
347
            glStencilFunc(GL_ALWAYS, 0, ~0U);
 
348
            glStencilOp(GL_KEEP, GL_KEEP, hasSTW ? GL_DECR_WRAP_EXT : GL_DECR);
 
349
        }
 
350
        else
 
351
        {
 
352
            glStencilFuncSeparate_(GL_ALWAYS, GL_ALWAYS, 0, ~0U);
 
353
            glStencilOpSeparate_(GL_BACK, GL_KEEP, GL_KEEP, hasSTW ? GL_INCR_WRAP_EXT : GL_INCR);
 
354
            glStencilOpSeparate_(GL_FRONT, GL_KEEP, GL_KEEP, hasSTW ? GL_DECR_WRAP_EXT : GL_DECR);
 
355
        }
 
356
 
 
357
        startmodelbatches();
 
358
        rendermapmodels();
 
359
        renderentities();
 
360
        renderclients();
 
361
        renderbounceents();
 
362
        endmodelbatches();
 
363
 
 
364
        if(hasST2) glDisable(GL_STENCIL_TEST_TWO_SIDE_EXT);
 
365
        glEnable(GL_CULL_FACE);
 
366
    }
 
367
    else
 
368
    {
 
369
        glStencilFunc(GL_ALWAYS, 0, ~0U);
 
370
        glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);
 
371
 
 
372
        startmodelbatches();
 
373
        rendermapmodels();
 
374
        renderentities();
 
375
        renderclients();
 
376
        renderbounceents();
 
377
        endmodelbatches(false);
 
378
 
 
379
        if(shadowcasters)
 
380
        {
 
381
            stenciling = 2;
 
382
 
 
383
            glStencilFunc(GL_ALWAYS, 0, ~0U);
 
384
            glStencilOp(GL_KEEP, GL_KEEP, GL_DECR);
 
385
            glCullFace(GL_BACK);
 
386
 
 
387
            endmodelbatches(true);
 
388
 
 
389
            glCullFace(GL_FRONT);
 
390
        }
 
391
        else clearmodelbatches();
 
392
    }
 
393
 
 
394
    stenciling = 0;
 
395
 
 
396
    glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
 
397
    glDepthMask(GL_TRUE);
 
398
 
 
399
    if(shadowcasters)
 
400
    {
 
401
        glDisable(GL_DEPTH_TEST);
 
402
 
 
403
        glStencilFunc(GL_NOTEQUAL, (hasST2 || hasSTS) && !hasSTW ? 128 : 0, ~0U);
 
404
        glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
 
405
 
 
406
        glEnable(GL_BLEND);
 
407
        glBlendFunc(GL_ZERO, GL_SRC_COLOR);
 
408
 
 
409
        float intensity = 1.0f - stencilshadow/100.0f;
 
410
        glColor3f(intensity, intensity, intensity);
 
411
 
 
412
        glMatrixMode(GL_PROJECTION);
 
413
        glLoadIdentity();
 
414
        glOrtho(0, 1, 0, 1, -1, 1);
 
415
 
 
416
        glMatrixMode(GL_MODELVIEW);
 
417
        glPushMatrix();
 
418
        glLoadIdentity();
 
419
 
 
420
        static uint debugtiles[SHADOWROWS+1];
 
421
        if(dbgtiles) memcpy(debugtiles, shadowtiles, sizeof(debugtiles));
 
422
 
 
423
        rendershadowtiles();
 
424
 
 
425
        if(dbgtiles)
 
426
        {
 
427
            glDisable(GL_STENCIL_TEST);
 
428
            glColor3f(0.5f, 1, 0.5f);
 
429
            memcpy(shadowtiles, debugtiles, sizeof(debugtiles));
 
430
            rendershadowtiles();
 
431
            glColor3f(0, 0, 1);
 
432
            glDisable(GL_BLEND);
 
433
            glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
 
434
            memcpy(shadowtiles, debugtiles, sizeof(debugtiles));
 
435
            rendershadowtiles();
 
436
            glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
 
437
        }
 
438
        else glDisable(GL_BLEND);
 
439
 
 
440
        glMatrixMode(GL_PROJECTION);
 
441
        glLoadIdentity();
 
442
        setperspective(fovy, aspect, 0.15f, farplane);
 
443
 
 
444
        glMatrixMode(GL_MODELVIEW);
 
445
        glPopMatrix();
 
446
 
 
447
        glEnable(GL_DEPTH_TEST);
 
448
    }
 
449
 
 
450
    // necessary to avoid ATI bug!
 
451
    // punts to software mode if separate stencil op is set, even while stencil disabled, when drawing lines!
 
452
    glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
 
453
 
 
454
    glDisable(GL_STENCIL_TEST);
 
455
    glEnable(GL_TEXTURE_2D);
 
456
    glEnable(GL_FOG);
 
457
}
 
458