Rev 885 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
5 | Plagman | 1 | /************************************************************************************************** |
2 | "POLYMOST" code written by Ken Silverman |
||
3 | Ken Silverman's official web site: http://www.advsys.net/ken |
||
4 | |||
5 | Motivation: |
||
6 | When 3D Realms released the Duke Nukem 3D source code, I thought somebody would do a OpenGL or |
||
7 | Direct3D port. Well, after a few months passed, I saw no sign of somebody working on a true |
||
8 | hardware-accelerated port of Build, just people saying it wasn't possible. Eventually, I realized |
||
9 | the only way this was going to happen was for me to do it myself. First, I needed to port Build to |
||
10 | Windows. I could have done it myself, but instead I thought I'd ask my Australian buddy, Jonathon |
||
11 | Fowler, if he would upgrade his Windows port to my favorite compiler (MSVC) - which he did. Once |
||
12 | that was done, I was ready to start the "POLYMOST" project. |
||
13 | |||
14 | About: |
||
15 | This source file is basically a complete rewrite of the entire rendering part of the Build engine. |
||
16 | There are small pieces in ENGINE.C to activate this code, and other minor hacks in other source |
||
17 | files, but most of it is in here. If you're looking for polymost-related code in the other source |
||
18 | files, you should find most of them by searching for either "polymost" or "rendmode". Speaking of |
||
19 | rendmode, there are now 4 rendering modes in Build: |
||
20 | |||
21 | rendmode 0: The original code I wrote from 1993-1997 |
||
22 | rendmode 1: Solid-color rendering: my debug code before I did texture mapping |
||
23 | rendmode 2: Software rendering before I started the OpenGL code (Note: this is just a quick |
||
24 | hack to make testing easier - it's not optimized to my usual standards!) |
||
25 | rendmode 3: The OpenGL code |
||
26 | |||
27 | The original Build engine did hidden surface removal by using a vertical span buffer on the tops |
||
28 | and bottoms of walls. This worked nice back in the day, but it it's not suitable for a polygon |
||
29 | engine. So I decided to write a brand new hidden surface removal algorithm - using the same idea |
||
30 | as the original Build - but one that worked with vectors instead of already rasterized data. |
||
31 | |||
32 | Brief history: |
||
33 | 06/20/2000: I release Build Source code |
||
34 | 04/01/2003: 3D Realms releases Duke Nukem 3D source code |
||
35 | 10/04/2003: Jonathon Fowler gets his Windows port working in Visual C |
||
36 | 10/04/2003: I start writing POLYMOST.BAS, a new hidden surface removal algorithm for Build that |
||
37 | works on a polygon level instead of spans. |
||
38 | 10/16/2003: Ported POLYMOST.BAS to C inside JonoF KenBuild's ENGINE.C; later this code was split |
||
39 | out of ENGINE.C and put in this file, POLYMOST.C. |
||
40 | 12/10/2003: Started OpenGL code for POLYMOST (rendmode 3) |
||
41 | 12/23/2003: 1st public release |
||
42 | 01/01/2004: 2nd public release: fixed stray lines, status bar, mirrors, sky, and lots of other bugs. |
||
43 | |||
44 | ---------------------------------------------------------------------------------------------------- |
||
45 | |||
46 | Todo list (in approximate chronological order): |
||
47 | |||
48 | High priority: |
||
49 | * BOTH: Do accurate software sorting/chopping for sprites: drawing in wrong order is bad :/ |
||
50 | * BOTH: Fix hall of mirrors near "zenith". Call polymost_drawrooms twice? |
||
51 | * OPENGL: drawmapview() |
||
52 | |||
53 | Low priority: |
||
54 | * SOFT6D: Do back-face culling of sprites during up/down/tilt transformation (top of drawpoly) |
||
55 | * SOFT6D: Fix depth shading: use saturation&LUT |
||
56 | * SOFT6D: Optimize using hyperbolic mapping (similar to KUBE algo) |
||
57 | * SOFT6D: Slab6-style voxel sprites. How to accelerate? :/ |
||
58 | * OPENGL: KENBUILD: Write flipping code for floor mirrors |
||
59 | * BOTH: KENBUILD: Parallaxing sky modes 1&2 |
||
60 | * BOTH: Masked/1-way walls don't clip correctly to sectors of intersecting ceiling/floor slopes |
||
61 | * BOTH: Editart x-center is not working correctly with Duke's camera/turret sprites |
||
62 | * BOTH: Get rid of horizontal line above Duke full-screen status bar |
||
63 | * BOTH: Combine ceilings/floors into a single triangle strip (should lower poly count by 2x) |
||
64 | * BOTH: Optimize/clean up texture-map setup equations |
||
65 | |||
66 | **************************************************************************************************/ |
||
67 | |||
584 | terminx | 68 | int animateoffs(short tilenum, short fakevar); |
697 | plagman | 69 | int rendmode=0; |
584 | terminx | 70 | int usemodels=1, usehightile=1; |
5 | Plagman | 71 | |
72 | #include <math.h> //<-important! |
||
584 | terminx | 73 | typedef struct { float x, cy[2], fy[2]; int n, p, tag, ctag, ftag; } vsptyp; |
5 | Plagman | 74 | #define VSPMAX 4096 //<- careful! |
75 | static vsptyp vsp[VSPMAX]; |
||
584 | terminx | 76 | static int vcnt, gtag; |
5 | Plagman | 77 | |
78 | static double dxb1[MAXWALLSB], dxb2[MAXWALLSB]; |
||
79 | |||
80 | #define SCISDIST 1.0 //1.0: Close plane clipping distance |
||
81 | #define USEZBUFFER 1 //1:use zbuffer (slow, nice sprite rendering), 0:no zbuffer (fast, bad sprite rendering) |
||
82 | #define LINTERPSIZ 4 //log2 of interpolation size. 4:pretty fast&acceptable quality, 0:best quality/slow! |
||
83 | #define DEPTHDEBUG 0 //1:render distance instead of texture, for debugging only!, 0:default |
||
431 | terminx | 84 | #define FOGSCALE 0.0000640 |
5 | Plagman | 85 | #define PI 3.14159265358979323 |
86 | |||
774 | plagman | 87 | float shadescale = 1.050; |
379 | terminx | 88 | |
5 | Plagman | 89 | static double gyxscale, gxyaspect, gviewxrange, ghalfx, grhalfxdown10, grhalfxdown10x, ghoriz; |
90 | static double gcosang, gsinang, gcosang2, gsinang2; |
||
91 | static double gchang, gshang, gctang, gstang, gvisibility; |
||
307 | Plagman | 92 | float gtang = 0.0; |
5 | Plagman | 93 | double guo, gux, guy; //Screen-based texture mapping parameters |
94 | double gvo, gvx, gvy; |
||
95 | double gdo, gdx, gdy; |
||
96 | |||
97 | #if (USEZBUFFER != 0) |
||
786 | qbix79 | 98 | int zbufysiz = 0, zbufbpl = 0, *zbufoff = 0; |
99 | intptr_t zbufmem = 0; |
||
5 | Plagman | 100 | #endif |
101 | |||
102 | #ifdef USE_OPENGL |
||
590 | plagman | 103 | static int srepeat = 0, trepeat = 0; |
104 | |||
584 | terminx | 105 | int glredbluemode = 0; |
106 | static int lastglredbluemode = 0, redblueclearcnt = 0; |
||
5 | Plagman | 107 | |
584 | terminx | 108 | static struct glfiltermodes |
109 | { |
||
109 | terminx | 110 | char *name; |
584 | terminx | 111 | int min,mag; |
112 | } glfiltermodes[] = |
||
113 | { |
||
114 | {"GL_NEAREST",GL_NEAREST,GL_NEAREST}, |
||
115 | {"GL_LINEAR",GL_LINEAR,GL_LINEAR}, |
||
116 | {"GL_NEAREST_MIPMAP_NEAREST",GL_NEAREST_MIPMAP_NEAREST,GL_NEAREST}, |
||
117 | {"GL_LINEAR_MIPMAP_NEAREST",GL_LINEAR_MIPMAP_NEAREST,GL_LINEAR}, |
||
118 | {"GL_NEAREST_MIPMAP_LINEAR",GL_NEAREST_MIPMAP_LINEAR,GL_NEAREST}, |
||
119 | {"GL_LINEAR_MIPMAP_LINEAR",GL_LINEAR_MIPMAP_LINEAR,GL_LINEAR} |
||
120 | }; |
||
5 | Plagman | 121 | #define numglfiltermodes (sizeof(glfiltermodes)/sizeof(glfiltermodes[0])) |
122 | |||
584 | terminx | 123 | int glanisotropy = 1; // 0 = maximum supported by card |
124 | int glusetexcompr = 1; |
||
125 | int gltexfiltermode = 2; // GL_NEAREST_MIPMAP_NEAREST |
||
126 | int glusetexcache = 0; |
||
127 | int glusetexcachecompression = 1; |
||
128 | int glmultisample = 0, glnvmultisamplehint = 0; |
||
129 | int gltexmaxsize = 0; // 0 means autodetection on first run |
||
130 | int gltexmiplevel = 0; // discards this many mipmap levels |
||
131 | static int lastglpolygonmode = 0; //FUK |
||
132 | int glpolygonmode = 0; // 0:GL_FILL,1:GL_LINE,2:GL_POINT //FUK |
||
133 | int glwidescreen = 0; |
||
134 | int glprojectionhacks = 1; |
||
5 | Plagman | 135 | static GLuint polymosttext = 0; |
136 | extern char nofog; |
||
228 | Plagman | 137 | |
244 | Plagman | 138 | // Those THREE globals control the drawing of fullbright tiles |
584 | terminx | 139 | static int fullbrightloadingpass = 0; |
140 | static int fullbrightdrawingpass = 0; |
||
141 | static int shadeforfullbrightpass; |
||
228 | Plagman | 142 | |
446 | Plagman | 143 | // Depth peeling control |
584 | terminx | 144 | int r_depthpeeling = 0; // cvar toggling general depth peeling usage |
145 | int r_peelscount = 5; // cvar controlling the number of peeling layers |
||
146 | int r_curpeel = -1; // cvar controlling the display of independant peeling layers |
||
498 | terminx | 147 | static float curpolygonoffset; // internal polygon offset stack for drawing flat sprites to avoid depth fighting |
584 | terminx | 148 | static int peelcompiling = 0; // internal control var to disable blending when compiling the peeling display list |
149 | static int newpeelscount = 0; // temporary var for peels count changing during the game |
||
446 | Plagman | 150 | |
151 | // Depth peeling data |
||
498 | terminx | 152 | static GLuint ztexture[3]; // secondary Z-buffers identifier |
153 | static GLuint *peels; // peels identifiers |
||
154 | static GLuint *peelfbos; // peels FBOs identifiers |
||
155 | static GLuint peelprogram[2]; // ARBfp peeling fragment program |
||
446 | Plagman | 156 | |
460 | Plagman | 157 | // Detail mapping cvar |
584 | terminx | 158 | int r_detailmapping = 1; |
459 | Plagman | 159 | |
497 | Plagman | 160 | // Glow mapping cvar |
584 | terminx | 161 | int r_glowmapping = 1; |
497 | Plagman | 162 | |
513 | Plagman | 163 | // Vertex Array model drawing cvar |
584 | terminx | 164 | int r_vertexarrays = 1; |
513 | Plagman | 165 | |
519 | Plagman | 166 | // Vertex Buffer Objects model drawing cvars |
584 | terminx | 167 | int r_vbos = 0; |
168 | int r_vbocount = 64; |
||
513 | Plagman | 169 | |
525 | Plagman | 170 | // model animation smoothing cvar |
584 | terminx | 171 | int r_animsmoothing = 1; |
519 | Plagman | 172 | |
623 | plagman | 173 | // polymost ART sky control |
174 | int r_parallaxskyclamping = 1; |
||
175 | int r_parallaxskypanning = 0; |
||
176 | |||
881 | terminx | 177 | // line of sight checks before mddraw() |
178 | int r_cullobstructedmodels = 0; |
||
882 | terminx | 179 | #define CULL_DELAY 5 |
881 | terminx | 180 | |
883 | terminx | 181 | // fullbright cvar |
886 | terminx | 182 | int r_fullbrights = 1; |
883 | terminx | 183 | |
621 | plagman | 184 | static float fogresult, fogcol[4]; |
393 | terminx | 185 | |
612 | terminx | 186 | // making this a macro should speed things up at the expense of code size |
187 | #define fogcalc(shade, vis, pal) \ |
||
188 | { \ |
||
622 | terminx | 189 | fogresult = (float)gvisibility*(vis+16+(shade<0?(-shade*shade)*0.125f:(shade*shade)*0.125f)); \ |
190 | if (vis > 239) fogresult = (float)gvisibility*((vis-240+(shade<0?(-shade*shade)*0.125f:(shade*shade)*0.125f))/(klabs(vis-256))); \ |
||
612 | terminx | 191 | fogresult = min(max(fogresult, 0.01f),10.f); \ |
192 | fogcol[0] = (float)palookupfog[pal].r / 63.f; \ |
||
193 | fogcol[1] = (float)palookupfog[pal].g / 63.f; \ |
||
194 | fogcol[2] = (float)palookupfog[pal].b / 63.f; \ |
||
195 | fogcol[3] = 0; \ |
||
356 | terminx | 196 | } |
5 | Plagman | 197 | #endif |
198 | |||
199 | #if defined(USE_MSC_PRAGMAS) |
||
584 | terminx | 200 | static inline void ftol(float f, int *a) |
5 | Plagman | 201 | { |
109 | terminx | 202 | _asm |
203 | { |
||
204 | mov eax, a |
||
205 | fld f |
||
206 | fistp dword ptr [eax] |
||
207 | } |
||
5 | Plagman | 208 | } |
209 | |||
584 | terminx | 210 | static inline void dtol(double d, int *a) |
5 | Plagman | 211 | { |
109 | terminx | 212 | _asm |
213 | { |
||
214 | mov eax, a |
||
215 | fld d |
||
216 | fistp dword ptr [eax] |
||
217 | } |
||
5 | Plagman | 218 | } |
219 | #elif defined(USE_WATCOM_PRAGMAS) |
||
220 | |||
221 | #pragma aux ftol =\ |
||
222 | "fistp dword ptr [eax]",\ |
||
223 | parm [eax 8087] |
||
224 | #pragma aux dtol =\ |
||
225 | "fistp dword ptr [eax]",\ |
||
226 | parm [eax 8087] |
||
227 | |||
228 | #elif defined(USE_GCC_PRAGMAS) |
||
229 | |||
584 | terminx | 230 | static inline void ftol(float f, int *a) |
5 | Plagman | 231 | { |
584 | terminx | 232 | __asm__ __volatile__( |
5 | Plagman | 233 | #if 0 //(__GNUC__ >= 3) |
109 | terminx | 234 | "flds %1; fistpl %0;" |
5 | Plagman | 235 | #else |
726 | terminx | 236 | "flds %1; fistpl (%0);" |
5 | Plagman | 237 | #endif |
584 | terminx | 238 | : "=r"(a) : "m"(f) : "memory","cc"); |
5 | Plagman | 239 | } |
240 | |||
584 | terminx | 241 | static inline void dtol(double d, int *a) |
5 | Plagman | 242 | { |
584 | terminx | 243 | __asm__ __volatile__( |
5 | Plagman | 244 | #if 0 //(__GNUC__ >= 3) |
109 | terminx | 245 | "fldl %1; fistpl %0;" |
5 | Plagman | 246 | #else |
726 | terminx | 247 | "fldl %1; fistpl (%0);" |
5 | Plagman | 248 | #endif |
584 | terminx | 249 | : "=r"(a) : "m"(d) : "memory","cc"); |
5 | Plagman | 250 | } |
251 | |||
252 | #else |
||
584 | terminx | 253 | static inline void ftol(float f, int *a) |
5 | Plagman | 254 | { |
584 | terminx | 255 | *a = (int)f; |
5 | Plagman | 256 | } |
257 | |||
584 | terminx | 258 | static inline void dtol(double d, int *a) |
5 | Plagman | 259 | { |
584 | terminx | 260 | *a = (int)d; |
5 | Plagman | 261 | } |
262 | #endif |
||
263 | |||
584 | terminx | 264 | static inline int imod(int a, int b) |
5 | Plagman | 265 | { |
109 | terminx | 266 | if (a >= 0) return(a%b); |
267 | return(((a+1)%b)+b-1); |
||
5 | Plagman | 268 | } |
269 | |||
584 | terminx | 270 | void drawline2d(float x0, float y0, float x1, float y1, char col) |
5 | Plagman | 271 | { |
109 | terminx | 272 | float f, dx, dy, fxres, fyres; |
584 | terminx | 273 | int e, inc, x, y; |
274 | unsigned int up16; |
||
5 | Plagman | 275 | |
109 | terminx | 276 | dx = x1-x0; dy = y1-y0; if ((dx == 0) && (dy == 0)) return; |
277 | fxres = (float)xdimen; fyres = (float)ydimen; |
||
584 | terminx | 278 | if (x0 >= fxres) { if (x1 >= fxres) return; y0 += (fxres-x0)*dy/dx; x0 = fxres; } |
279 | else if (x0 < 0) { if (x1 < 0) return; y0 += (0-x0)*dy/dx; x0 = 0; } |
||
280 | if (x1 >= fxres) { y1 += (fxres-x1)*dy/dx; x1 = fxres; } |
||
281 | else if (x1 < 0) { y1 += (0-x1)*dy/dx; x1 = 0; } |
||
109 | terminx | 282 | if (y0 >= fyres) { if (y1 >= fyres) return; x0 += (fyres-y0)*dx/dy; y0 = fyres; } |
584 | terminx | 283 | else if (y0 < 0) { if (y1 < 0) return; x0 += (0-y0)*dx/dy; y0 = 0; } |
284 | if (y1 >= fyres) { x1 += (fyres-y1)*dx/dy; y1 = fyres; } |
||
285 | else if (y1 < 0) { x1 += (0-y1)*dx/dy; y1 = 0; } |
||
5 | Plagman | 286 | |
109 | terminx | 287 | if (fabs(dx) > fabs(dy)) |
288 | { |
||
289 | if (x0 > x1) { f = x0; x0 = x1; x1 = f; f = y0; y0 = y1; y1 = f; } |
||
584 | terminx | 290 | y = (int)(y0*65536.f)+32768; |
291 | inc = (int)(dy/dx*65536.f+.5f); |
||
292 | x = (int)(x0+.5); if (x < 0) { y -= inc*x; x = 0; } //if for safety |
||
293 | e = (int)(x1+.5); if (e > xdimen) e = xdimen; //if for safety |
||
109 | terminx | 294 | up16 = (ydimen<<16); |
584 | terminx | 295 | for (;x<e;x++,y+=inc) if ((unsigned int)y < up16) *(char *)(ylookup[y>>16]+x+frameoffset) = col; |
109 | terminx | 296 | } |
297 | else |
||
298 | { |
||
299 | if (y0 > y1) { f = x0; x0 = x1; x1 = f; f = y0; y0 = y1; y1 = f; } |
||
584 | terminx | 300 | x = (int)(x0*65536.f)+32768; |
301 | inc = (int)(dx/dy*65536.f+.5f); |
||
302 | y = (int)(y0+.5); if (y < 0) { x -= inc*y; y = 0; } //if for safety |
||
303 | e = (int)(y1+.5); if (e > ydimen) e = ydimen; //if for safety |
||
109 | terminx | 304 | up16 = (xdimen<<16); |
584 | terminx | 305 | for (;y<e;y++,x+=inc) if ((unsigned int)x < up16) *(char *)(ylookup[y]+(x>>16)+frameoffset) = col; |
109 | terminx | 306 | } |
5 | Plagman | 307 | } |
308 | |||
309 | #ifdef USE_OPENGL |
||
310 | typedef struct { unsigned char r, g, b, a; } coltype; |
||
311 | |||
584 | terminx | 312 | static void uploadtexture(int doalloc, int xsiz, int ysiz, int intexfmt, int texfmt, coltype *pic, int tsizx, int tsizy, int dameth); |
5 | Plagman | 313 | |
314 | #include "md4.h" |
||
315 | |||
316 | #define USELZF |
||
317 | #define USEKENFILTER 1 |
||
318 | |||
319 | #ifdef USELZF |
||
320 | # include "lzf.h" |
||
321 | #else |
||
322 | # include "lzwnew.h" |
||
323 | #endif |
||
324 | |||
325 | static char TEXCACHEDIR[] = "texcache"; |
||
584 | terminx | 326 | typedef struct |
327 | { |
||
109 | terminx | 328 | char magic[8]; // 'Polymost' |
584 | terminx | 329 | int xdim, ydim; // of image, unpadded |
330 | int flags; // 1 = !2^x, 2 = has alpha, 4 = lzw compressed |
||
5 | Plagman | 331 | } texcacheheader; |
584 | terminx | 332 | typedef struct |
333 | { |
||
334 | int size; |
||
335 | int format; |
||
336 | int xdim, ydim; // of mipmap (possibly padded) |
||
337 | int border, depth; |
||
5 | Plagman | 338 | } texcachepicture; |
339 | |||
584 | terminx | 340 | int dxtfilter(int fil, texcachepicture *pict, char *pic, void *midbuf, char *packbuf, unsigned int miplen); |
5 | Plagman | 341 | int dedxtfilter(int fil, texcachepicture *pict, char *pic, void *midbuf, char *packbuf, int ispacked); |
342 | |||
343 | static inline void phex(unsigned char v, char *s); |
||
584 | terminx | 344 | void writexcache(char *fn, int len, int dameth, char effect, texcacheheader *head); |
5 | Plagman | 345 | |
606 | terminx | 346 | int mdtims, omdtims; |
5 | Plagman | 347 | float alphahackarray[MAXTILES]; |
348 | #include "mdsprite.c" |
||
349 | |||
350 | //-------------------------------------------------------------------------------------------------- |
||
351 | //TEXTURE MANAGEMENT: treats same texture with different .PAL as a separate texture. This makes the |
||
352 | // max number of virtual textures very large (MAXTILES*256). Instead of allocating a handle for |
||
353 | // every virtual texture, I use a cache where indexing is managed through a hash table. |
||
354 | // |
||
355 | |||
283 | Plagman | 356 | // moved into polymost.h |
357 | /*typedef struct pthtyp_t |
||
5 | Plagman | 358 | { |
109 | terminx | 359 | struct pthtyp_t *next; |
360 | GLuint glpic; |
||
361 | short picnum; |
||
362 | char palnum; |
||
363 | char effects; |
||
228 | Plagman | 364 | char flags; // 1 = clamped (dameth&4), 2 = hightile, 4 = skybox face, 8 = hasalpha, 16 = hasfullbright, 128 = invalidated |
109 | terminx | 365 | char skyface; |
366 | hicreplctyp *hicr; |
||
5 | Plagman | 367 | |
109 | terminx | 368 | unsigned short sizx, sizy; |
369 | float scalex, scaley; |
||
235 | Plagman | 370 | struct pthtyp_t *wofb; // without fullbright |
371 | struct pthtyp_t *ofb; // only fullbright |
||
286 | terminx | 372 | } pthtyp;*/ |
5 | Plagman | 373 | |
374 | #define GLTEXCACHEADSIZ 8192 |
||
375 | static pthtyp *gltexcachead[GLTEXCACHEADSIZ]; |
||
376 | |||
779 | plagman | 377 | int drawingskybox = 0; |
5 | Plagman | 378 | |
587 | terminx | 379 | pthtyp *pichead; |
380 | |||
584 | terminx | 381 | int gloadtile_art(int,int,int,pthtyp*,int); |
587 | terminx | 382 | int gloadtile_hi(int,int,int,hicreplctyp*,int,pthtyp*,int,char); |
5 | Plagman | 383 | static int hicprecaching = 0; |
584 | terminx | 384 | pthtyp * gltexcache(int dapicnum, int dapalnum, int dameth) |
5 | Plagman | 385 | { |
584 | terminx | 386 | int i, j; |
109 | terminx | 387 | hicreplctyp *si; |
499 | Plagman | 388 | pthtyp *pth, *pth2; |
5 | Plagman | 389 | |
109 | terminx | 390 | j = (dapicnum&(GLTEXCACHEADSIZ-1)); |
5 | Plagman | 391 | |
109 | terminx | 392 | if (usehightile) si = hicfindsubst(dapicnum,dapalnum,drawingskybox); |
393 | else si = NULL; |
||
584 | terminx | 394 | if (!si) |
395 | { |
||
109 | terminx | 396 | if (drawingskybox) return NULL; |
397 | goto tryart; |
||
398 | } |
||
5 | Plagman | 399 | |
109 | terminx | 400 | /* if palette > 0 && replacement found |
401 | * no effects are applied to the texture |
||
402 | * else if palette > 0 && no replacement found |
||
403 | * effects are applied to the palette 0 texture if it exists |
||
404 | */ |
||
5 | Plagman | 405 | |
587 | terminx | 406 | pichead=gltexcachead[j]; // for palmaps |
109 | terminx | 407 | // load a replacement |
587 | terminx | 408 | for (pth=pichead; pth; pth=pth->next) |
584 | terminx | 409 | { |
109 | terminx | 410 | if (pth->picnum == dapicnum && |
411 | pth->palnum == si->palnum && |
||
412 | (si->palnum>0 ? 1 : (pth->effects == hictinting[dapalnum].f)) && |
||
413 | (pth->flags & (1+2+4)) == (((dameth&4)>>2)+2+((drawingskybox>0)<<2)) && |
||
414 | (drawingskybox>0 ? (pth->skyface == drawingskybox) : 1) |
||
415 | ) |
||
416 | { |
||
417 | if (pth->flags & 128) |
||
418 | { |
||
419 | pth->flags &= ~128; |
||
587 | terminx | 420 | if (gloadtile_hi(dapicnum,dapalnum,drawingskybox,si,dameth,pth,0, |
584 | terminx | 421 | (si->palnum>0) ? 0 : hictinting[dapalnum].f)) // reload tile |
422 | { |
||
109 | terminx | 423 | if (drawingskybox) return NULL; |
424 | goto tryart; // failed, so try for ART |
||
425 | } |
||
426 | } |
||
427 | return(pth); |
||
428 | } |
||
429 | } |
||
5 | Plagman | 430 | |
499 | Plagman | 431 | |
109 | terminx | 432 | pth = (pthtyp *)calloc(1,sizeof(pthtyp)); |
433 | if (!pth) return NULL; |
||
5 | Plagman | 434 | |
499 | Plagman | 435 | // possibly fetch an already loaded multitexture :_) |
436 | if (dapalnum >= (MAXPALOOKUPS - RESERVEDPALS)) |
||
437 | for (i = (GLTEXCACHEADSIZ - 1); i >= 0; i--) |
||
584 | terminx | 438 | for (pth2=gltexcachead[i]; pth2; pth2=pth2->next) |
439 | { |
||
499 | Plagman | 440 | if ((pth2->hicr) && (pth2->hicr->filename) && (Bstrcasecmp(pth2->hicr->filename, si->filename) == 0)) |
441 | { |
||
442 | memcpy(pth, pth2, sizeof(pthtyp)); |
||
443 | pth->picnum = dapicnum; |
||
515 | terminx | 444 | pth->flags = ((dameth&4)>>2) + 2 + ((drawingskybox>0)<<2); |
519 | Plagman | 445 | if (pth2->flags & 8) pth->flags |= 8; //hasalpha |
499 | Plagman | 446 | pth->hicr = si; |
447 | pth->next = gltexcachead[j]; |
||
723 | terminx | 448 | |
499 | Plagman | 449 | gltexcachead[j] = pth; |
450 | return(pth); |
||
451 | } |
||
452 | } |
||
453 | |||
587 | terminx | 454 | if (gloadtile_hi(dapicnum,dapalnum,drawingskybox,si,dameth,pth,1, (si->palnum>0) ? 0 : hictinting[dapalnum].f)) |
584 | terminx | 455 | { |
109 | terminx | 456 | free(pth); |
457 | if (drawingskybox) return NULL; |
||
458 | goto tryart; // failed, so try for ART |
||
459 | } |
||
460 | pth->palnum = si->palnum; |
||
461 | pth->next = gltexcachead[j]; |
||
462 | gltexcachead[j] = pth; |
||
463 | return(pth); |
||
5 | Plagman | 464 | |
465 | tryart: |
||
109 | terminx | 466 | if (hicprecaching) return NULL; |
5 | Plagman | 467 | |
109 | terminx | 468 | // load from art |
331 | terminx | 469 | for (pth=gltexcachead[j]; pth; pth=pth->next) |
109 | terminx | 470 | if (pth->picnum == dapicnum && |
471 | pth->palnum == dapalnum && |
||
472 | (pth->flags & (1+2)) == ((dameth&4)>>2) |
||
473 | ) |
||
474 | { |
||
235 | Plagman | 475 | if (pth->flags & 128) |
109 | terminx | 476 | { |
248 | terminx | 477 | pth->flags &= ~128; |
109 | terminx | 478 | if (gloadtile_art(dapicnum,dapalnum,dameth,pth,0)) return NULL; //reload tile (for animations) |
479 | } |
||
480 | return(pth); |
||
481 | } |
||
5 | Plagman | 482 | |
109 | terminx | 483 | pth = (pthtyp *)calloc(1,sizeof(pthtyp)); |
484 | if (!pth) return NULL; |
||
5 | Plagman | 485 | |
584 | terminx | 486 | if (gloadtile_art(dapicnum,dapalnum,dameth,pth,1)) |
487 | { |
||
109 | terminx | 488 | free(pth); |
489 | return NULL; |
||
490 | } |
||
491 | pth->next = gltexcachead[j]; |
||
492 | gltexcachead[j] = pth; |
||
235 | Plagman | 493 | |
109 | terminx | 494 | return(pth); |
5 | Plagman | 495 | } |
496 | |||
584 | terminx | 497 | int gltexmayhavealpha(int dapicnum, int dapalnum) |
5 | Plagman | 498 | { |
584 | terminx | 499 | int j = (dapicnum&(GLTEXCACHEADSIZ-1)); |
109 | terminx | 500 | pthtyp *pth; |
5 | Plagman | 501 | |
331 | terminx | 502 | for (pth=gltexcachead[j]; pth; pth=pth->next) |
109 | terminx | 503 | if ((pth->picnum == dapicnum) && (pth->palnum == dapalnum)) |
504 | return((pth->flags&8) != 0); |
||
505 | return(1); |
||
5 | Plagman | 506 | } |
507 | |||
584 | terminx | 508 | void gltexinvalidate(int dapicnum, int dapalnum, int dameth) |
5 | Plagman | 509 | { |
654 | terminx | 510 | int j; |
109 | terminx | 511 | pthtyp *pth; |
5 | Plagman | 512 | |
109 | terminx | 513 | j = (dapicnum&(GLTEXCACHEADSIZ-1)); |
331 | terminx | 514 | for (pth=gltexcachead[j]; pth; pth=pth->next) |
584 | terminx | 515 | if (pth->picnum == dapicnum && pth->palnum == dapalnum && (pth->flags & 1) == ((dameth&4)>>2)) |
248 | terminx | 516 | { |
517 | pth->flags |= 128; |
||
518 | if (pth->flags & 16) |
||
519 | pth->ofb->flags |= 128; |
||
520 | } |
||
5 | Plagman | 521 | } |
522 | |||
109 | terminx | 523 | //Make all textures "dirty" so they reload, but not re-allocate |
524 | //This should be much faster than polymost_glreset() |
||
525 | //Use this for palette effects ... but not ones that change every frame! |
||
584 | terminx | 526 | void gltexinvalidateall() |
5 | Plagman | 527 | { |
584 | terminx | 528 | int j; |
109 | terminx | 529 | pthtyp *pth; |
5 | Plagman | 530 | |
331 | terminx | 531 | for (j=GLTEXCACHEADSIZ-1;j>=0;j--) |
532 | for (pth=gltexcachead[j];pth;pth=pth->next) |
||
248 | terminx | 533 | { |
109 | terminx | 534 | pth->flags |= 128; |
248 | terminx | 535 | if (pth->flags & 16) |
536 | pth->ofb->flags |= 128; |
||
537 | } |
||
109 | terminx | 538 | clearskins(); |
5 | Plagman | 539 | #ifdef DEBUGGINGAIDS |
109 | terminx | 540 | OSD_Printf("gltexinvalidateall()\n"); |
5 | Plagman | 541 | #endif |
542 | } |
||
543 | |||
584 | terminx | 544 | void gltexinvalidate8() |
415 | terminx | 545 | { |
584 | terminx | 546 | int j; |
415 | terminx | 547 | pthtyp *pth; |
5 | Plagman | 548 | |
415 | terminx | 549 | for (j=GLTEXCACHEADSIZ-1;j>=0;j--) |
550 | for (pth=gltexcachead[j];pth;pth=pth->next) |
||
551 | { |
||
552 | if (pth->hicr == NULL) |
||
553 | { |
||
554 | pth->flags |= 128; |
||
555 | if (pth->flags & 16) |
||
556 | pth->ofb->flags |= 128; |
||
557 | } |
||
558 | } |
||
559 | #ifdef DEBUGGINGAIDS |
||
560 | OSD_Printf("gltexinvalidate8()\n"); |
||
561 | #endif |
||
562 | } |
||
563 | |||
584 | terminx | 564 | void gltexapplyprops(void) |
5 | Plagman | 565 | { |
584 | terminx | 566 | int i; |
109 | terminx | 567 | pthtyp *pth; |
5 | Plagman | 568 | |
109 | terminx | 569 | if (glinfo.maxanisotropy > 1.0) |
570 | { |
||
584 | terminx | 571 | if (glanisotropy <= 0 || glanisotropy > glinfo.maxanisotropy) glanisotropy = (int)glinfo.maxanisotropy; |
109 | terminx | 572 | } |
5 | Plagman | 573 | |
109 | terminx | 574 | if (gltexfiltermode < 0) gltexfiltermode = 0; |
584 | terminx | 575 | else if (gltexfiltermode >= (int)numglfiltermodes) gltexfiltermode = numglfiltermodes-1; |
576 | for (i=GLTEXCACHEADSIZ-1;i>=0;i--) |
||
577 | { |
||
578 | for (pth=gltexcachead[i];pth;pth=pth->next) |
||
579 | { |
||
109 | terminx | 580 | bglBindTexture(GL_TEXTURE_2D,pth->glpic); |
581 | bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,glfiltermodes[gltexfiltermode].mag); |
||
582 | bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,glfiltermodes[gltexfiltermode].min); |
||
583 | if (glinfo.maxanisotropy > 1.0) |
||
584 | bglTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAX_ANISOTROPY_EXT,glanisotropy); |
||
886 | terminx | 585 | if (r_fullbrights && pth->flags & 16) |
248 | terminx | 586 | { |
587 | bglBindTexture(GL_TEXTURE_2D,pth->ofb->glpic); |
||
588 | bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,glfiltermodes[gltexfiltermode].mag); |
||
589 | bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,glfiltermodes[gltexfiltermode].min); |
||
590 | if (glinfo.maxanisotropy > 1.0) |
||
591 | bglTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAX_ANISOTROPY_EXT,glanisotropy); |
||
592 | } |
||
109 | terminx | 593 | } |
594 | } |
||
5 | Plagman | 595 | |
109 | terminx | 596 | { |
597 | int j; |
||
598 | mdskinmap_t *sk; |
||
599 | md2model *m; |
||
600 | |||
601 | for (i=0;i<nextmodelid;i++) |
||
602 | { |
||
603 | m = (md2model *)models[i]; |
||
604 | if (m->mdnum < 2) continue; |
||
605 | for (j=0;j<m->numskins*(HICEFFECTMASK+1);j++) |
||
606 | { |
||
607 | if (!m->texid[j]) continue; |
||
608 | bglBindTexture(GL_TEXTURE_2D,m->texid[j]); |
||
609 | bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,glfiltermodes[gltexfiltermode].mag); |
||
610 | bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,glfiltermodes[gltexfiltermode].min); |
||
611 | if (glinfo.maxanisotropy > 1.0) |
||
612 | bglTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAX_ANISOTROPY_EXT,glanisotropy); |
||
613 | } |
||
614 | |||
615 | for (sk=m->skinmap;sk;sk=sk->next) |
||
616 | for (j=0;j<(HICEFFECTMASK+1);j++) |
||
617 | { |
||
618 | if (!sk->texid[j]) continue; |
||
619 | bglBindTexture(GL_TEXTURE_2D,sk->texid[j]); |
||
620 | bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,glfiltermodes[gltexfiltermode].mag); |
||
621 | bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,glfiltermodes[gltexfiltermode].min); |
||
622 | if (glinfo.maxanisotropy > 1.0) |
||
623 | bglTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAX_ANISOTROPY_EXT,glanisotropy); |
||
624 | } |
||
625 | } |
||
626 | } |
||
5 | Plagman | 627 | } |
628 | |||
629 | //-------------------------------------------------------------------------------------------------- |
||
630 | |||
631 | static float glox1, gloy1, glox2, gloy2; |
||
632 | |||
109 | terminx | 633 | //Use this for both initialization and uninitialization of OpenGL. |
5 | Plagman | 634 | static int gltexcacnum = -1; |
584 | terminx | 635 | void polymost_glreset() |
5 | Plagman | 636 | { |
584 | terminx | 637 | int i; |
109 | terminx | 638 | pthtyp *pth, *next; |
639 | //Reset if this is -1 (meaning 1st texture call ever), or > 0 (textures in memory) |
||
640 | if (gltexcacnum < 0) |
||
641 | { |
||
642 | gltexcacnum = 0; |
||
5 | Plagman | 643 | |
109 | terminx | 644 | //Hack for polymost_dorotatesprite calls before 1st polymost_drawrooms() |
645 | gcosang = gcosang2 = ((double)16384)/262144.0; |
||
646 | gsinang = gsinang2 = ((double) 0)/262144.0; |
||
647 | } |
||
648 | else |
||
649 | { |
||
584 | terminx | 650 | for (i=GLTEXCACHEADSIZ-1; i>=0; i--) |
651 | { |
||
652 | for (pth=gltexcachead[i]; pth;) |
||
653 | { |
||
109 | terminx | 654 | next = pth->next; |
248 | terminx | 655 | if (pth->flags & 16) // fullbright textures |
656 | { |
||
657 | bglDeleteTextures(1,&pth->ofb->glpic); |
||
658 | free(pth->ofb); |
||
659 | } |
||
109 | terminx | 660 | bglDeleteTextures(1,&pth->glpic); |
587 | terminx | 661 | if (pth->palmap) |
662 | { |
||
663 | //_initprintf("Kill #%d\n",pth->palmap); |
||
664 | free(pth->palmap);pth->palmap=0; |
||
665 | } |
||
109 | terminx | 666 | free(pth); |
667 | pth = next; |
||
668 | } |
||
669 | gltexcachead[i] = NULL; |
||
670 | } |
||
671 | clearskins(); |
||
672 | } |
||
673 | |||
674 | if (polymosttext) bglDeleteTextures(1,&polymosttext); |
||
675 | polymosttext=0; |
||
676 | |||
677 | memset(gltexcachead,0,sizeof(gltexcachead)); |
||
678 | glox1 = -1; |
||
446 | Plagman | 679 | |
680 | // Depth peeling cleanup |
||
681 | if (peels) |
||
682 | { |
||
454 | Plagman | 683 | bglDeleteProgramsARB(2, peelprogram); |
684 | bglDeleteFramebuffersEXT(r_peelscount + 1, peelfbos); |
||
685 | bglDeleteTextures(r_peelscount + 1, peels); |
||
686 | bglDeleteTextures(3, ztexture); |
||
446 | Plagman | 687 | free(peels); |
688 | free(peelfbos); |
||
689 | |||
690 | peels = NULL; |
||
691 | } |
||
5 | Plagman | 692 | } |
693 | |||
627 | terminx | 694 | // one-time initialization of OpenGL for polymost |
5 | Plagman | 695 | void polymost_glinit() |
696 | { |
||
109 | terminx | 697 | GLfloat col[4]; |
439 | Plagman | 698 | int i; |
584 | terminx | 699 | char notpeeledprogramstring[] = |
700 | "!!ARBfp1.0\n" |
||
701 | "OPTION ARB_fog_exp2;\n" |
||
702 | "OPTION ARB_fragment_program_shadow;\n" |
||
703 | "TEMP texsample;\n" |
||
704 | "TEMP depthresult;\n" |
||
705 | "TEX depthresult, fragment.position, texture[1], SHADOWRECT;\n" |
||
706 | "ADD depthresult.a, depthresult.a, -0.5;\n" |
||
707 | "KIL depthresult.a;\n" |
||
708 | "TEX texsample, fragment.texcoord[0], texture[0], 2D;\n" |
||
709 | "MUL result.color, fragment.color, texsample;\n" |
||
710 | "END\n"; |
||
711 | char peeledprogramstring[] = |
||
712 | "!!ARBfp1.0\n" |
||
713 | "OPTION ARB_fog_exp2;\n" |
||
714 | "OPTION ARB_fragment_program_shadow;\n" |
||
715 | "TEMP texsample;\n" |
||
716 | "TEMP depthresult;\n" |
||
717 | "TEX depthresult, fragment.position, texture[2], SHADOWRECT;\n" |
||
718 | "ADD depthresult.a, depthresult.a, -0.5;\n" |
||
719 | "KIL depthresult.a;\n" |
||
720 | "TEX depthresult, fragment.position, texture[1], SHADOWRECT;\n" |
||
721 | "ADD depthresult.a, depthresult.a, -0.5;\n" |
||
722 | "KIL depthresult.a;\n" |
||
723 | "TEX texsample, fragment.texcoord[0], texture[0], 2D;\n" |
||
724 | "MUL result.color, fragment.color, texsample;\n" |
||
725 | "END\n"; |
||
5 | Plagman | 726 | |
415 | terminx | 727 | #if 1 |
387 | terminx | 728 | if (!Bstrcmp(glinfo.vendor, "ATI Technologies Inc.")) |
729 | { |
||
730 | initprintf("polymost_glinit(): ATI detected, GL_FOG_HINT = GL_DONT_CARE\n"); |
||
731 | bglHint(GL_FOG_HINT,GL_DONT_CARE); |
||
732 | } |
||
733 | else |
||
734 | { |
||
735 | bglHint(GL_FOG_HINT,GL_NICEST); |
||
736 | } |
||
404 | terminx | 737 | #else |
738 | bglHint(GL_FOG_HINT,GL_DONT_CARE); |
||
739 | #endif |
||
584 | terminx | 740 | |
503 | Plagman | 741 | bglFogi(GL_FOG_MODE,GL_EXP2); |
109 | terminx | 742 | bglFogf(GL_FOG_DENSITY,1.0); //must be > 0, default is 1 |
584 | terminx | 743 | /* bglFogf(GL_FOG_START,0.0); //default is 0 |
744 | bglFogf(GL_FOG_END,1.0); //default is 1 */ |
||
109 | terminx | 745 | col[0] = 0; col[1] = 0; col[2] = 0; col[3] = 0; //range:0 to 1 |
746 | bglFogfv(GL_FOG_COLOR,col); //default is 0,0,0,0 |
||
5 | Plagman | 747 | |
109 | terminx | 748 | bglBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); |
749 | |||
118 | terminx | 750 | //bglHint(GL_LINE_SMOOTH_HINT, GL_NICEST); |
751 | //bglEnable(GL_LINE_SMOOTH); |
||
752 | |||
584 | terminx | 753 | if (glmultisample > 0 && glinfo.multisample) |
754 | { |
||
109 | terminx | 755 | if (glinfo.nvmultisamplehint) |
756 | bglHint(GL_MULTISAMPLE_FILTER_HINT_NV, glnvmultisamplehint ? GL_NICEST:GL_FASTEST); |
||
757 | bglEnable(GL_MULTISAMPLE_ARB); |
||
758 | } |
||
439 | Plagman | 759 | |
459 | Plagman | 760 | if (r_depthpeeling && (!glinfo.arbfp || !glinfo.depthtex || !glinfo.shadow || !glinfo.fbos || !glinfo.rect || !glinfo.multitex)) |
439 | Plagman | 761 | { |
459 | Plagman | 762 | OSD_Printf("Your OpenGL implementation doesn't support depth peeling. Disabling...\n"); |
446 | Plagman | 763 | r_depthpeeling = 0; |
764 | } |
||
765 | |||
497 | Plagman | 766 | if (r_detailmapping && (!glinfo.multitex || !glinfo.envcombine)) |
459 | Plagman | 767 | { |
768 | OSD_Printf("Your OpenGL implementation doesn't support detail mapping. Disabling...\n"); |
||
460 | Plagman | 769 | r_detailmapping = 0; |
459 | Plagman | 770 | } |
771 | |||
497 | Plagman | 772 | if (r_glowmapping && (!glinfo.multitex || !glinfo.envcombine)) |
773 | { |
||
774 | OSD_Printf("Your OpenGL implementation doesn't support glow mapping. Disabling...\n"); |
||
775 | r_glowmapping = 0; |
||
776 | } |
||
777 | |||
519 | Plagman | 778 | if (r_vbos && (!glinfo.vbos)) |
779 | { |
||
780 | OSD_Printf("Your OpenGL implementation doesn't support Vertex Buffer Objects. Disabling...\n"); |
||
781 | r_vbos = 0; |
||
782 | } |
||
783 | |||
446 | Plagman | 784 | //depth peeling initialization |
785 | if (r_depthpeeling) |
||
786 | { |
||
787 | if (newpeelscount) |
||
788 | { |
||
789 | r_peelscount = newpeelscount; |
||
790 | newpeelscount = 0; |
||
791 | } |
||
454 | Plagman | 792 | // create the secondary Z-buffers and the Z-backbuffer |
497 | Plagman | 793 | bglGenTextures(3, ztexture); |
794 | |||
795 | i = 0; |
||
796 | while (i < 3) |
||
797 | { |
||
798 | bglBindTexture(GL_TEXTURE_RECTANGLE, ztexture[i]); |
||
799 | bglCopyTexImage2D(GL_TEXTURE_RECTANGLE, 0, GL_DEPTH_COMPONENT, 0, 0, xdim, ydim, 0); |
||
800 | bglTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
||
801 | bglTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
||
802 | bglTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_S, GL_CLAMP); |
||
803 | bglTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_T, GL_CLAMP); |
||
804 | bglTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB); |
||
805 | if (i < 2) |
||
806 | bglTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_COMPARE_FUNC_ARB, GL_GREATER); |
||
807 | else |
||
808 | bglTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LESS); |
||
809 | bglTexParameteri(GL_TEXTURE_RECTANGLE, GL_DEPTH_TEXTURE_MODE_ARB, GL_ALPHA); |
||
810 | |||
811 | i++; |
||
812 | } |
||
813 | |||
814 | // create the various peeling layers as well as the FBOs to render to them |
||
815 | peels = malloc((r_peelscount + 1) * sizeof(GLuint)); |
||
816 | bglGenTextures(r_peelscount + 1, peels); |
||
817 | |||
818 | peelfbos = malloc((r_peelscount + 1) * sizeof(GLuint)); |
||
819 | bglGenFramebuffersEXT(r_peelscount + 1, peelfbos); |
||
820 | |||
821 | i = 0; |
||
822 | while (i <= r_peelscount) |
||
823 | { |
||
824 | bglBindTexture(GL_TEXTURE_RECTANGLE, peels[i]); |
||
825 | bglCopyTexImage2D(GL_TEXTURE_RECTANGLE, 0, GL_RGBA, 0, 0, xdim, ydim, 0); |
||
826 | bglTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
||
827 | bglTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
||
828 | bglTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_S, GL_CLAMP); |
||
829 | bglTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_T, GL_CLAMP); |
||
830 | |||
831 | bglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, peelfbos[i]); |
||
832 | bglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE, peels[i], 0); |
||
833 | if (i == r_peelscount) // bakcbuffer |
||
834 | bglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_RECTANGLE, ztexture[2], 0); |
||
454 | Plagman | 835 | else if (i < (r_peelscount - 1)) |
497 | Plagman | 836 | bglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_RECTANGLE, ztexture[i % 2], 0); |
837 | |||
838 | if (bglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT) |
||
839 | { |
||
840 | OSD_Printf("FBO #%d initialization failed.\n", i); |
||
841 | } |
||
842 | |||
446 | Plagman | 843 | bglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); |
497 | Plagman | 844 | |
845 | i++; |
||
846 | } |
||
847 | |||
848 | // create the peeling fragment programs |
||
849 | bglGenProgramsARB(2, peelprogram); |
||
850 | bglBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, peelprogram[0]); |
||
851 | bglProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, strlen(notpeeledprogramstring), notpeeledprogramstring); |
||
852 | bglBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, peelprogram[1]); |
||
853 | bglProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, strlen(peeledprogramstring), peeledprogramstring); |
||
439 | Plagman | 854 | } |
513 | Plagman | 855 | |
856 | bglEnableClientState(GL_VERTEX_ARRAY); |
||
857 | bglEnableClientState(GL_TEXTURE_COORD_ARRAY); |
||
5 | Plagman | 858 | } |
859 | |||
584 | terminx | 860 | void resizeglcheck() |
5 | Plagman | 861 | { |
109 | terminx | 862 | float m[4][4]; |
26 | terminx | 863 | int fovcorrect; |
5 | Plagman | 864 | |
584 | terminx | 865 | if (glredbluemode < lastglredbluemode) |
866 | { |
||
109 | terminx | 867 | glox1 = -1; |
868 | bglColorMask(1,1,1,1); |
||
584 | terminx | 869 | } |
870 | else if (glredbluemode != lastglredbluemode) |
||
871 | { |
||
109 | terminx | 872 | redblueclearcnt = 0; |
873 | } |
||
874 | lastglredbluemode = glredbluemode; |
||
5 | Plagman | 875 | |
109 | terminx | 876 | //FUK |
877 | if (lastglpolygonmode != glpolygonmode) |
||
878 | { |
||
879 | lastglpolygonmode = glpolygonmode; |
||
331 | terminx | 880 | switch (glpolygonmode) |
109 | terminx | 881 | { |
882 | default: |
||
331 | terminx | 883 | case 0: |
884 | bglPolygonMode(GL_FRONT_AND_BACK,GL_FILL); break; |
||
885 | case 1: |
||
886 | bglPolygonMode(GL_FRONT_AND_BACK,GL_LINE); break; |
||
887 | case 2: |
||
888 | bglPolygonMode(GL_FRONT_AND_BACK,GL_POINT); break; |
||
109 | terminx | 889 | } |
890 | } |
||
891 | if (glpolygonmode) //FUK |
||
892 | { |
||
893 | bglClearColor(1.0,1.0,1.0,0.0); |
||
894 | bglClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); |
||
895 | bglDisable(GL_TEXTURE_2D); |
||
896 | } |
||
5 | Plagman | 897 | |
109 | terminx | 898 | if ((glox1 != windowx1) || (gloy1 != windowy1) || (glox2 != windowx2) || (gloy2 != windowy2)) |
899 | { |
||
900 | glox1 = windowx1; gloy1 = windowy1; |
||
901 | glox2 = windowx2; gloy2 = windowy2; |
||
902 | |||
204 | terminx | 903 | fovcorrect = glprojectionhacks?(glwidescreen?0:(((windowx2-windowx1+1) * 1.2) - (windowx2-windowx1+1))):0; |
5 | Plagman | 904 | |
109 | terminx | 905 | bglViewport(windowx1 - (fovcorrect / 2), yres-(windowy2+1),windowx2-windowx1+1 + fovcorrect, windowy2-windowy1+1); |
5 | Plagman | 906 | |
109 | terminx | 907 | bglMatrixMode(GL_PROJECTION); |
908 | memset(m,0,sizeof(m)); |
||
204 | terminx | 909 | m[0][0] = (float)ydimen / (glprojectionhacks?1.2:1); m[0][2] = 1.0; |
109 | terminx | 910 | m[1][1] = (float)xdimen; m[1][2] = 1.0; |
204 | terminx | 911 | m[2][2] = 1.0; m[2][3] = (float)ydimen / (glprojectionhacks?1.2:1); |
109 | terminx | 912 | m[3][2] =-1.0; |
913 | bglLoadMatrixf(&m[0][0]); |
||
914 | //bglLoadIdentity(); |
||
5 | Plagman | 915 | |
109 | terminx | 916 | bglMatrixMode(GL_MODELVIEW); |
917 | bglLoadIdentity(); |
||
5 | Plagman | 918 | |
109 | terminx | 919 | if (!nofog) bglEnable(GL_FOG); |
5 | Plagman | 920 | |
109 | terminx | 921 | //bglEnable(GL_TEXTURE_2D); |
922 | } |
||
5 | Plagman | 923 | } |
924 | |||
584 | terminx | 925 | void fixtransparency(coltype *dapic, int daxsiz, int daysiz, int daxsiz2, int daysiz2, int dameth) |
5 | Plagman | 926 | { |
109 | terminx | 927 | coltype *wpptr; |
584 | terminx | 928 | int j, x, y, r, g, b, dox, doy, naxsiz2; |
5 | Plagman | 929 | |
109 | terminx | 930 | dox = daxsiz2-1; doy = daysiz2-1; |
931 | if (dameth&4) { dox = min(dox,daxsiz); doy = min(doy,daysiz); } |
||
932 | else { daxsiz = daxsiz2; daysiz = daysiz2; } //Make repeating textures duplicate top/left parts |
||
5 | Plagman | 933 | |
109 | terminx | 934 | daxsiz--; daysiz--; naxsiz2 = -daxsiz2; //Hacks for optimization inside loop |
5 | Plagman | 935 | |
109 | terminx | 936 | //Set transparent pixels to average color of neighboring opaque pixels |
937 | //Doing this makes bilinear filtering look much better for masked textures (I.E. sprites) |
||
331 | terminx | 938 | for (y=doy;y>=0;y--) |
109 | terminx | 939 | { |
940 | wpptr = &dapic[y*daxsiz2+dox]; |
||
331 | terminx | 941 | for (x=dox;x>=0;x--,wpptr--) |
109 | terminx | 942 | { |
943 | if (wpptr->a) continue; |
||
944 | r = g = b = j = 0; |
||
584 | terminx | 945 | if ((x> 0) && (wpptr[ -1].a)) { r += (int)wpptr[ -1].r; g += (int)wpptr[ -1].g; b += (int)wpptr[ -1].b; j++; } |
946 | if ((x<daxsiz) && (wpptr[ +1].a)) { r += (int)wpptr[ +1].r; g += (int)wpptr[ +1].g; b += (int)wpptr[ +1].b; j++; } |
||
947 | if ((y> 0) && (wpptr[naxsiz2].a)) { r += (int)wpptr[naxsiz2].r; g += (int)wpptr[naxsiz2].g; b += (int)wpptr[naxsiz2].b; j++; } |
||
948 | if ((y<daysiz) && (wpptr[daxsiz2].a)) { r += (int)wpptr[daxsiz2].r; g += (int)wpptr[daxsiz2].g; b += (int)wpptr[daxsiz2].b; j++; } |
||
331 | terminx | 949 | switch (j) |
109 | terminx | 950 | { |
331 | terminx | 951 | case 1: |
952 | wpptr->r = r ; wpptr->g = g ; wpptr->b = b ; break; |
||
953 | case 2: |
||
954 | wpptr->r = ((r + 1)>>1); wpptr->g = ((g + 1)>>1); wpptr->b = ((b + 1)>>1); break; |
||
955 | case 3: |
||
956 | wpptr->r = ((r*85+128)>>8); wpptr->g = ((g*85+128)>>8); wpptr->b = ((b*85+128)>>8); break; |
||
957 | case 4: |
||
958 | wpptr->r = ((r + 2)>>2); wpptr->g = ((g + 2)>>2); wpptr->b = ((b + 2)>>2); break; |
||
959 | default: |
||
960 | break; |
||
109 | terminx | 961 | } |
962 | } |
||
963 | } |
||
5 | Plagman | 964 | } |
965 | |||
584 | terminx | 966 | static void uploadtexture(int doalloc, int xsiz, int ysiz, int intexfmt, int texfmt, coltype *pic, int tsizx, int tsizy, int dameth) |
5 | Plagman | 967 | { |
109 | terminx | 968 | coltype *wpptr, *rpptr; |
584 | terminx | 969 | int x2, y2, j, js=0, x3, y3, y, x, r, g, b, a, k; |
5 | Plagman | 970 | |
584 | terminx | 971 | if (gltexmaxsize <= 0) |
972 | { |
||
109 | terminx | 973 | GLint i = 0; |
974 | bglGetIntegerv(GL_MAX_TEXTURE_SIZE, &i); |
||
975 | if (!i) gltexmaxsize = 6; // 2^6 = 64 == default GL max texture size |
||
584 | terminx | 976 | else |
977 | { |
||
109 | terminx | 978 | gltexmaxsize = 0; |
979 | for (; i>1; i>>=1) gltexmaxsize++; |
||
980 | } |
||
981 | } |
||
5 | Plagman | 982 | |
109 | terminx | 983 | js = max(0,min(gltexmaxsize-1,gltexmiplevel)); |
984 | gltexmiplevel = js; |
||
985 | while ((xsiz>>js) > (1<<gltexmaxsize) || (ysiz>>js) > (1<<gltexmaxsize)) js++; |
||
5 | Plagman | 986 | |
109 | terminx | 987 | /* |
988 | OSD_Printf("Uploading %dx%d %s as %s\n", xsiz,ysiz, |
||
989 | (texfmt==GL_RGBA?"GL_RGBA": |
||
990 | texfmt==GL_RGB?"GL_RGB": |
||
991 | texfmt==GL_BGR?"GL_BGR": |
||
992 | texfmt==GL_BGRA?"GL_BGRA":"other"), |
||
993 | (intexfmt==GL_RGBA?"GL_RGBA": |
||
994 | intexfmt==GL_RGB?"GL_RGB": |
||
995 | intexfmt==GL_COMPRESSED_RGBA_ARB?"GL_COMPRESSED_RGBA_ARB": |
||
996 | intexfmt==GL_COMPRESSED_RGB_ARB?"GL_COMPRESSED_RGB_ARB":"other")); |
||
997 | */ |
||
998 | |||
584 | terminx | 999 | if (js == 0) |
1000 | { |
||
109 | terminx | 1001 | if (doalloc&1) |
1002 | bglTexImage2D(GL_TEXTURE_2D,0,intexfmt,xsiz,ysiz,0,texfmt,GL_UNSIGNED_BYTE,pic); //loading 1st time |
||
1003 | else |
||
1004 | bglTexSubImage2D(GL_TEXTURE_2D,0,0,0,xsiz,ysiz,texfmt,GL_UNSIGNED_BYTE,pic); //overwrite old texture |
||
1005 | } |
||
1006 | |||
5 | Plagman | 1007 | #if 0 |
109 | terminx | 1008 | gluBuild2DMipmaps(GL_TEXTURE_2D,GL_RGBA8,xsiz,ysiz,texfmt,GL_UNSIGNED_BYTE,pic); //Needs C++ to link? |
5 | Plagman | 1009 | #elif 1 |
109 | terminx | 1010 | x2 = xsiz; y2 = ysiz; |
331 | terminx | 1011 | for (j=1;(x2 > 1) || (y2 > 1);j++) |
109 | terminx | 1012 | { |
1013 | //x3 = ((x2+1)>>1); y3 = ((y2+1)>>1); |
||
1014 | x3 = max(1, x2 >> 1); y3 = max(1, y2 >> 1); // this came from the GL_ARB_texture_non_power_of_two spec |
||
331 | terminx | 1015 | for (y=0;y<y3;y++) |
109 | terminx | 1016 | { |
1017 | wpptr = &pic[y*x3]; rpptr = &pic[(y<<1)*x2]; |
||
331 | terminx | 1018 | for (x=0;x<x3;x++,wpptr++,rpptr+=2) |
109 | terminx | 1019 | { |
1020 | r = g = b = a = k = 0; |
||
584 | terminx | 1021 | if (rpptr[0].a) { r += (int)rpptr[0].r; g += (int)rpptr[0].g; b += (int)rpptr[0].b; a += (int)rpptr[0].a; k++; } |
1022 | if ((x+x+1 < x2) && (rpptr[1].a)) { r += (int)rpptr[1].r; g += (int)rpptr[1].g; b += (int)rpptr[1].b; a += (int)rpptr[1].a; k++; } |
||
109 | terminx | 1023 | if (y+y+1 < y2) |
1024 | { |
||
584 | terminx | 1025 | if ((rpptr[x2].a)) { r += (int)rpptr[x2 ].r; g += (int)rpptr[x2 ].g; b += (int)rpptr[x2 ].b; a += (int)rpptr[x2 ].a; k++; } |
1026 | if ((x+x+1 < x2) && (rpptr[x2+1].a)) { r += (int)rpptr[x2+1].r; g += (int)rpptr[x2+1].g; b += (int)rpptr[x2+1].b; a += (int)rpptr[x2+1].a; k++; } |
||
109 | terminx | 1027 | } |
331 | terminx | 1028 | switch (k) |
109 | terminx | 1029 | { |
1030 | case 0: |
||
331 | terminx | 1031 | case 1: |
1032 | wpptr->r = r; wpptr->g = g; wpptr->b = b; wpptr->a = a; break; |
||
1033 | case 2: |
||
1034 | wpptr->r = ((r+1)>>1); wpptr->g = ((g+1)>>1); wpptr->b = ((b+1)>>1); wpptr->a = ((a+1)>>1); break; |
||
1035 | case 3: |
||
1036 | wpptr->r = ((r*85+128)>>8); wpptr->g = ((g*85+128)>>8); wpptr->b = ((b*85+128)>>8); wpptr->a = ((a*85+128)>>8); break; |
||
1037 | case 4: |
||
1038 | wpptr->r = ((r+2)>>2); wpptr->g = ((g+2)>>2); wpptr->b = ((b+2)>>2); wpptr->a = ((a+2)>>2); break; |
||
1039 | default: |
||
1040 | break; |
||
109 | terminx | 1041 | } |
1042 | //if (wpptr->a) wpptr->a = 255; |
||
1043 | } |
||
1044 | } |
||
1045 | if (tsizx >= 0) fixtransparency(pic,(tsizx+(1<<j)-1)>>j,(tsizy+(1<<j)-1)>>j,x3,y3,dameth); |
||
584 | terminx | 1046 | if (j >= js) |
1047 | { |
||
109 | terminx | 1048 | if (doalloc&1) |
1049 | bglTexImage2D(GL_TEXTURE_2D,j-js,intexfmt,x3,y3,0,texfmt,GL_UNSIGNED_BYTE,pic); //loading 1st time |
||
1050 | else |
||
1051 | bglTexSubImage2D(GL_TEXTURE_2D,j-js,0,0,x3,y3,texfmt,GL_UNSIGNED_BYTE,pic); //overwrite old texture |
||
1052 | } |
||
1053 | x2 = x3; y2 = y3; |
||
1054 | } |
||
5 | Plagman | 1055 | #endif |
1056 | } |
||
1057 | |||
584 | terminx | 1058 | int gloadtile_art(int dapic, int dapal, int dameth, pthtyp *pth, int doalloc) |
5 | Plagman | 1059 | { |
109 | terminx | 1060 | coltype *pic, *wpptr; |
654 | terminx | 1061 | int x, y, x2, y2, xsiz, ysiz, dacol, tsizx, tsizy; |
228 | Plagman | 1062 | char hasalpha = 0, hasfullbright = 0; |
5 | Plagman | 1063 | |
109 | terminx | 1064 | tsizx = tilesizx[dapic]; |
1065 | tsizy = tilesizy[dapic]; |
||
584 | terminx | 1066 | if (!glinfo.texnpot) |
1067 | { |
||
331 | terminx | 1068 | for (xsiz=1;xsiz<tsizx;xsiz+=xsiz); |
1069 | for (ysiz=1;ysiz<tsizy;ysiz+=ysiz); |
||
584 | terminx | 1070 | } |
1071 | else |
||
1072 | { |
||
1073 | if ((tsizx|tsizy) == 0) |
||
1074 | { |
||
109 | terminx | 1075 | xsiz = ysiz = 1; |
584 | terminx | 1076 | } |
1077 | else |
||
1078 | { |
||
109 | terminx | 1079 | xsiz = tsizx; |
1080 | ysiz = tsizy; |
||
1081 | } |
||
1082 | } |
||
5 | Plagman | 1083 | |
109 | terminx | 1084 | pic = (coltype *)malloc(xsiz*ysiz*sizeof(coltype)); |
1085 | if (!pic) return 1; |
||
5 | Plagman | 1086 | |
109 | terminx | 1087 | if (!waloff[dapic]) |
1088 | { |
||
1089 | //Force invalid textures to draw something - an almost purely transparency texture |
||
1090 | //This allows the Z-buffer to be updated for mirrors (which are invalidated textures) |
||
1091 | pic[0].r = pic[0].g = pic[0].b = 0; pic[0].a = 1; |
||
1092 | tsizx = tsizy = 1; hasalpha = 1; |
||
1093 | } |
||
1094 | else |
||
1095 | { |
||
331 | terminx | 1096 | for (y=0;y<ysiz;y++) |
109 | terminx | 1097 | { |
1098 | if (y < tsizy) y2 = y; else y2 = y-tsizy; |
||
1099 | wpptr = &pic[y*xsiz]; |
||
331 | terminx | 1100 | for (x=0;x<xsiz;x++,wpptr++) |
109 | terminx | 1101 | { |
1102 | if ((dameth&4) && ((x >= tsizx) || (y >= tsizy))) //Clamp texture |
||
584 | terminx | 1103 | { wpptr->r = wpptr->g = wpptr->b = wpptr->a = 0; continue; } |
109 | terminx | 1104 | if (x < tsizx) x2 = x; else x2 = x-tsizx; |
584 | terminx | 1105 | dacol = (int)(*(unsigned char *)(waloff[dapic]+x2*tsizy+y2)); |
248 | terminx | 1106 | if (!fullbrightloadingpass) |
584 | terminx | 1107 | { |
1108 | // regular texture |
||
248 | terminx | 1109 | if ((dacol > 239) && (dacol != 255)) |
1110 | hasfullbright = 1; |
||
1111 | wpptr->a = 255; |
||
1112 | } |
||
1113 | else if (fullbrightloadingpass == 1) |
||
584 | terminx | 1114 | { |
1115 | // texture with only fullbright areas |
||
1116 | if (dacol < 240) // regular colors |
||
1117 | { |
||
248 | terminx | 1118 | wpptr->a = 0; hasalpha = 1; |
584 | terminx | 1119 | } |
1120 | else // fullbright |
||
1121 | { |
||
248 | terminx | 1122 | wpptr->a = 255; |
1123 | } |
||
1124 | } |
||
1125 | if (dacol != 255) |
||
584 | terminx | 1126 | dacol = (int)((unsigned char)palookup[dapal][dacol]); |
1127 | else |
||
1128 | { |
||
248 | terminx | 1129 | wpptr->a = 0; hasalpha = 1; |
1130 | } |
||
584 | terminx | 1131 | if (gammabrightness) |
1132 | { |
||
109 | terminx | 1133 | wpptr->r = curpalette[dacol].r; |
1134 | wpptr->g = curpalette[dacol].g; |
||
1135 | wpptr->b = curpalette[dacol].b; |
||
584 | terminx | 1136 | } |
1137 | else |
||
1138 | { |
||
109 | terminx | 1139 | wpptr->r = britable[curbrightness][ curpalette[dacol].r ]; |
1140 | wpptr->g = britable[curbrightness][ curpalette[dacol].g ]; |
||
1141 | wpptr->b = britable[curbrightness][ curpalette[dacol].b ]; |
||
1142 | } |
||
1143 | } |
||
1144 | } |
||
1145 | } |
||
5 | Plagman | 1146 | |
109 | terminx | 1147 | if (doalloc) bglGenTextures(1,(GLuint*)&pth->glpic); //# of textures (make OpenGL allocate structure) |
1148 | bglBindTexture(GL_TEXTURE_2D,pth->glpic); |
||
5 | Plagman | 1149 | |
109 | terminx | 1150 | fixtransparency(pic,tsizx,tsizy,xsiz,ysiz,dameth); |
1151 | uploadtexture(doalloc,xsiz,ysiz,hasalpha?GL_RGBA:GL_RGB,GL_RGBA,pic,tsizx,tsizy,dameth); |
||
5 | Plagman | 1152 | |
109 | terminx | 1153 | if (gltexfiltermode < 0) gltexfiltermode = 0; |
584 | terminx | 1154 | else if (gltexfiltermode >= (int)numglfiltermodes) gltexfiltermode = numglfiltermodes-1; |
109 | terminx | 1155 | bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,glfiltermodes[gltexfiltermode].mag); |
1156 | bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,glfiltermodes[gltexfiltermode].min); |
||
5 | Plagman | 1157 | |
109 | terminx | 1158 | if (glinfo.maxanisotropy > 1.0) |
1159 | { |
||
584 | terminx | 1160 | if (glanisotropy <= 0 || glanisotropy > glinfo.maxanisotropy) glanisotropy = (int)glinfo.maxanisotropy; |
109 | terminx | 1161 | bglTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAX_ANISOTROPY_EXT,glanisotropy); |
1162 | } |
||
5 | Plagman | 1163 | |
109 | terminx | 1164 | if (!(dameth&4)) |
1165 | { |
||
1166 | bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT); |
||
1167 | bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT); |
||
1168 | } |
||
1169 | else |
||
584 | terminx | 1170 | { |
1171 | //For sprite textures, clamping looks better than wrapping |
||
109 | terminx | 1172 | bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,glinfo.clamptoedge?GL_CLAMP_TO_EDGE:GL_CLAMP); |
1173 | bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,glinfo.clamptoedge?GL_CLAMP_TO_EDGE:GL_CLAMP); |
||
1174 | } |
||
5 | Plagman | 1175 | |
109 | terminx | 1176 | if (pic) free(pic); |
5 | Plagman | 1177 | |
109 | terminx | 1178 | pth->picnum = dapic; |
1179 | pth->palnum = dapal; |
||
1180 | pth->effects = 0; |
||
228 | Plagman | 1181 | pth->flags = ((dameth&4)>>2) | (hasalpha<<3) | (hasfullbright<<4); |
109 | terminx | 1182 | pth->hicr = NULL; |
1183 | |||
248 | terminx | 1184 | if ((hasfullbright) && (!fullbrightloadingpass)) |
1185 | { |
||
1186 | // load the ONLY texture that'll be assembled with the regular one to make the final texture with fullbright pixels |
||
1187 | fullbrightloadingpass = 1; |
||
1188 | pth->ofb = (pthtyp *)calloc(1,sizeof(pthtyp)); |
||
1189 | if (!pth->ofb) return 1; |
||
1190 | if (gloadtile_art(dapic, dapal, dameth, pth->ofb, 1)) return 1; |
||
235 | Plagman | 1191 | |
248 | terminx | 1192 | fullbrightloadingpass = 0; |
1193 | } |
||
109 | terminx | 1194 | return 0; |
5 | Plagman | 1195 | } |
1196 | |||
1197 | // JONOF'S COMPRESSED TEXTURE CACHE STUFF --------------------------------------------------- |
||
1198 | static inline void phex(unsigned char v, char *s) |
||
1199 | { |
||
109 | terminx | 1200 | int x; |
1201 | x = v>>4; |
||
1202 | s[0] = x<10 ? (x+'0') : (x-10+'a'); |
||
1203 | x = v&15; |
||
1204 | s[1] = x<10 ? (x+'0') : (x-10+'a'); |
||
5 | Plagman | 1205 | } |
1206 | |||
584 | terminx | 1207 | int trytexcache(char *fn, int len, int dameth, char effect, texcacheheader *head) |
5 | Plagman | 1208 | { |
584 | terminx | 1209 | int fil, fp; |
109 | terminx | 1210 | char cachefn[BMAX_PATH], *cp; |
1211 | unsigned char mdsum[16]; |
||
1212 | |||
1213 | if (!glinfo.texcompr || !glusetexcompr || !glusetexcache) return -1; |
||
584 | terminx | 1214 | if (!bglCompressedTexImage2DARB || !bglGetCompressedTexImageARB) |
1215 | { |
||
109 | terminx | 1216 | // lacking the necessary extensions to do this |
1217 | initprintf("Warning: the GL driver lacks necessary functions to use caching\n"); |
||
1218 | glusetexcache = 0; |
||
1219 | return -1; |
||
1220 | } |
||
1221 | |||
194 | terminx | 1222 | md4once((unsigned char *)fn, strlen(fn), mdsum); |
109 | terminx | 1223 | for (cp = cachefn, fp = 0; (*cp = TEXCACHEDIR[fp]); cp++,fp++); |
1224 | *(cp++) = '/'; |
||
1225 | for (fp = 0; fp < 16; phex(mdsum[fp++], cp), cp+=2); |
||
584 | terminx | 1226 | sprintf(cp, "-%x-%x%x", len, dameth, effect); |
109 | terminx | 1227 | |
1228 | fil = kopen4load(cachefn, 0); |
||
1229 | if (fil < 0) return -1; |
||
1230 | |||
1231 | /* initprintf("Loading cached tex: %s\n", cachefn); */ |
||
1232 | |||
1233 | if (kread(fil, head, sizeof(texcacheheader)) < (int)sizeof(texcacheheader)) goto failure; |
||
1234 | if (memcmp(head->magic, "Polymost", 8)) goto failure; |
||
1235 | |||
1236 | head->xdim = B_LITTLE32(head->xdim); |
||
1237 | head->ydim = B_LITTLE32(head->ydim); |
||
1238 | head->flags = B_LITTLE32(head->flags); |
||
1239 | |||
883 | terminx | 1240 | if (gltexmaxsize && (head->xdim > (1<<gltexmaxsize) || head->ydim > (1<<gltexmaxsize))) goto failure; |
109 | terminx | 1241 | if (!glinfo.texnpot && (head->flags & 1)) goto failure; |
1242 | |||
1243 | return fil; |
||
5 | Plagman | 1244 | failure: |
109 | terminx | 1245 | kclose(fil); |
1246 | return -1; |
||
5 | Plagman | 1247 | } |
1248 | |||
584 | terminx | 1249 | void writexcache(char *fn, int len, int dameth, char effect, texcacheheader *head) |
5 | Plagman | 1250 | { |
584 | terminx | 1251 | int fil=-1, fp; |
109 | terminx | 1252 | char cachefn[BMAX_PATH], *cp; |
1253 | unsigned char mdsum[16]; |
||
1254 | texcachepicture pict; |
||
1255 | char *pic = NULL, *packbuf = NULL; |
||
1256 | void *midbuf = NULL; |
||
584 | terminx | 1257 | unsigned int alloclen=0, level, miplen; |
1258 | unsigned int padx=0, pady=0; |
||
109 | terminx | 1259 | GLuint gi; |
5 | Plagman | 1260 | |
728 | terminx | 1261 | if (!glinfo.texcompr || !glusetexcompr || !glusetexcache) {initprintf("\n");return;} |
584 | terminx | 1262 | if (!bglCompressedTexImage2DARB || !bglGetCompressedTexImageARB) |
1263 | { |
||
109 | terminx | 1264 | // lacking the necessary extensions to do this |
1265 | initprintf("Warning: the GL driver lacks necessary functions to use caching\n"); |
||
1266 | glusetexcache = 0; |
||
1267 | return; |
||
1268 | } |
||
5 | Plagman | 1269 | |
109 | terminx | 1270 | { |
1271 | struct stat st; |
||
584 | terminx | 1272 | if (stat(TEXCACHEDIR, &st) < 0) |
1273 | { |
||
1274 | if (errno == ENOENT) // path doesn't exist |
||
1275 | { |
||
109 | terminx | 1276 | // try to create the cache directory |
584 | terminx | 1277 | if (Bmkdir(TEXCACHEDIR, S_IRWXU) < 0) |
1278 | { |
||
109 | terminx | 1279 | initprintf("Failed to create texture cache directory %s\n", TEXCACHEDIR); |
1280 | glusetexcache = 0; |
||
1281 | return; |
||
584 | terminx | 1282 | } |
1283 | else initprintf("Created texture cache directory %s\n", TEXCACHEDIR); |
||
1284 | } |
||
1285 | else |
||
1286 | { |
||
109 | terminx | 1287 | // another type of failure |
1288 | glusetexcache = 0; |
||
1289 | return; |
||
1290 | } |
||
584 | terminx | 1291 | } |
1292 | else if ((st.st_mode & S_IFDIR) != S_IFDIR) |
||
1293 | { |
||
109 | terminx | 1294 | // cache directory isn't a directory |
1295 | glusetexcache = 0; |
||
1296 | return; |
||
1297 | } |
||
1298 | } |
||
5 | Plagman | 1299 | |
109 | terminx | 1300 | gi = GL_FALSE; |
347 | terminx | 1301 | bglGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_COMPRESSED_ARB, (GLint *)&gi); |
109 | terminx | 1302 | if (gi != GL_TRUE) return; |
5 | Plagman | 1303 | |
194 | terminx | 1304 | md4once((unsigned char *)fn, strlen(fn), mdsum); |
109 | terminx | 1305 | for (cp = cachefn, fp = 0; (*cp = TEXCACHEDIR[fp]); cp++,fp++); |
1306 | *(cp++) = '/'; |
||
1307 | for (fp = 0; fp < 16; phex(mdsum[fp++], cp), cp+=2); |
||
584 | terminx | 1308 | sprintf(cp, "-%x-%x%x", len, dameth, effect); |
5 | Plagman | 1309 | |
109 | terminx | 1310 | initprintf("Writing cached tex: %s\n", cachefn); |
5 | Plagman | 1311 | |
109 | terminx | 1312 | fil = Bopen(cachefn,BO_BINARY|BO_CREAT|BO_TRUNC|BO_RDWR,BS_IREAD|BS_IWRITE); |
1313 | if (fil < 0) return; |
||
5 | Plagman | 1314 | |
109 | terminx | 1315 | memcpy(head->magic, "Polymost", 8); // sizes are set by caller |
5 | Plagman | 1316 | |
109 | terminx | 1317 | if (glusetexcachecompression) head->flags |= 4; |
5 | Plagman | 1318 | |
109 | terminx | 1319 | head->xdim = B_LITTLE32(head->xdim); |
1320 | head->ydim = B_LITTLE32(head->ydim); |
||
1321 | head->flags = B_LITTLE32(head->flags); |
||
5 | Plagman | 1322 | |
109 | terminx | 1323 | if (Bwrite(fil, head, sizeof(texcacheheader)) != sizeof(texcacheheader)) goto failure; |
5 | Plagman | 1324 | |
109 | terminx | 1325 | bglGetError(); |
584 | terminx | 1326 | for (level = 0; level==0 || (padx > 1 || pady > 1); level++) |
1327 | { |
||
347 | terminx | 1328 | bglGetTexLevelParameteriv(GL_TEXTURE_2D, level, GL_TEXTURE_COMPRESSED_ARB, (GLint *)&gi); |
109 | terminx | 1329 | if (bglGetError() != GL_NO_ERROR) goto failure; |
1330 | if (gi != GL_TRUE) goto failure; // an uncompressed mipmap |
||
347 | terminx | 1331 | bglGetTexLevelParameteriv(GL_TEXTURE_2D, level, GL_TEXTURE_INTERNAL_FORMAT, (GLint *)&gi); |
109 | terminx | 1332 | if (bglGetError() != GL_NO_ERROR) goto failure; |
1333 | pict.format = B_LITTLE32(gi); |
||
347 | terminx | 1334 | bglGetTexLevelParameteriv(GL_TEXTURE_2D, level, GL_TEXTURE_WIDTH, (GLint *)&gi); |
109 | terminx | 1335 | if (bglGetError() != GL_NO_ERROR) goto failure; |
1336 | padx = gi; pict.xdim = B_LITTLE32(gi); |
||
347 | terminx | 1337 | bglGetTexLevelParameteriv(GL_TEXTURE_2D, level, GL_TEXTURE_HEIGHT, (GLint *)&gi); |
109 | terminx | 1338 | if (bglGetError() != GL_NO_ERROR) goto failure; |
1339 | pady = gi; pict.ydim = B_LITTLE32(gi); |
||
347 | terminx | 1340 | bglGetTexLevelParameteriv(GL_TEXTURE_2D, level, GL_TEXTURE_BORDER, (GLint *)&gi); |
109 | terminx | 1341 | if (bglGetError() != GL_NO_ERROR) goto failure; |
1342 | pict.border = B_LITTLE32(gi); |
||
347 | terminx | 1343 | bglGetTexLevelParameteriv(GL_TEXTURE_2D, level, GL_TEXTURE_DEPTH, (GLint *)&gi); |
109 | terminx | 1344 | if (bglGetError() != GL_NO_ERROR) goto failure; |
1345 | pict.depth = B_LITTLE32(gi); |
||
347 | terminx | 1346 | bglGetTexLevelParameteriv(GL_TEXTURE_2D, level, GL_TEXTURE_COMPRESSED_IMAGE_SIZE_ARB, (GLint *)&gi); |
109 | terminx | 1347 | if (bglGetError() != GL_NO_ERROR) goto failure; |
584 | terminx | 1348 | miplen = (int)gi; pict.size = B_LITTLE32(gi); |
5 | Plagman | 1349 | |
584 | terminx | 1350 | if (alloclen < miplen) |
1351 | { |
||
109 | terminx | 1352 | void *picc = realloc(pic, miplen); |
1353 | if (!picc) goto failure; else pic = picc; |
||
1354 | alloclen = miplen; |
||
5 | Plagman | 1355 | |
109 | terminx | 1356 | picc = realloc(packbuf, alloclen+16); |
1357 | if (!picc) goto failure; else packbuf = picc; |
||
5 | Plagman | 1358 | |
109 | terminx | 1359 | picc = realloc(midbuf, miplen); |
1360 | if (!picc) goto failure; else midbuf = picc; |
||
1361 | } |
||
5 | Plagman | 1362 | |
109 | terminx | 1363 | bglGetCompressedTexImageARB(GL_TEXTURE_2D, level, pic); |
1364 | if (bglGetError() != GL_NO_ERROR) goto failure; |
||
5 | Plagman | 1365 | |
109 | terminx | 1366 | if (Bwrite(fil, &pict, sizeof(texcachepicture)) != sizeof(texcachepicture)) goto failure; |
1367 | if (dxtfilter(fil, &pict, pic, midbuf, packbuf, miplen)) goto failure; |
||
1368 | } |
||
5 | Plagman | 1369 | |
1370 | failure: |
||
109 | terminx | 1371 | if (fil>=0) Bclose(fil); |
1372 | if (midbuf) free(midbuf); |
||
1373 | if (pic) free(pic); |
||
1374 | if (packbuf) free(packbuf); |
||
5 | Plagman | 1375 | } |
1376 | |||
587 | terminx | 1377 | int gloadtile_cached(int fil, texcacheheader *head, int *doalloc, pthtyp *pth,int dapalnum) |
5 | Plagman | 1378 | { |
109 | terminx | 1379 | int level, r; |
1380 | texcachepicture pict; |
||
1381 | char *pic = NULL, *packbuf = NULL; |
||
1382 | void *midbuf = NULL; |
||
584 | terminx | 1383 | int alloclen=0; |
5 | Plagman | 1384 | |
654 | terminx | 1385 | UNREFERENCED_PARAMETER(dapalnum); |
1386 | |||
584 | terminx | 1387 | if (*doalloc&1) |
1388 | { |
||
109 | terminx | 1389 | bglGenTextures(1,(GLuint*)&pth->glpic); //# of textures (make OpenGL allocate structure) |
1390 | *doalloc |= 2; // prevents bglGenTextures being called again if we fail in here |
||
1391 | } |
||
1392 | bglBindTexture(GL_TEXTURE_2D,pth->glpic); |
||
5 | Plagman | 1393 | |
109 | terminx | 1394 | pth->sizx = head->xdim; |
1395 | pth->sizy = head->ydim; |
||
5 | Plagman | 1396 | |
109 | terminx | 1397 | bglGetError(); |
5 | Plagman | 1398 | |
109 | terminx | 1399 | // load the mipmaps |
584 | terminx | 1400 | for (level = 0; level==0 || (pict.xdim > 1 || pict.ydim > 1); level++) |
1401 | { |
||
109 | terminx | 1402 | r = kread(fil, &pict, sizeof(texcachepicture)); |
1403 | if (r < (int)sizeof(texcachepicture)) goto failure; |
||
5 | Plagman | 1404 | |
109 | terminx | 1405 | pict.size = B_LITTLE32(pict.size); |
1406 | pict.format = B_LITTLE32(pict.format); |
||
1407 | pict.xdim = B_LITTLE32(pict.xdim); |
||
1408 | pict.ydim = B_LITTLE32(pict.ydim); |
||
1409 | pict.border = B_LITTLE32(pict.border); |
||
1410 | pict.depth = B_LITTLE32(pict.depth); |
||
5 | Plagman | 1411 | |
584 | terminx | 1412 | if (alloclen < pict.size) |
1413 | { |
||
109 | terminx | 1414 | void *picc = realloc(pic, pict.size); |
1415 | if (!picc) goto failure; else pic = picc; |
||
1416 | alloclen = pict.size; |
||
5 | Plagman | 1417 | |
109 | terminx | 1418 | picc = realloc(packbuf, alloclen+16); |
1419 | if (!picc) goto failure; else packbuf = picc; |
||
5 | Plagman | 1420 | |
109 | terminx | 1421 | picc = realloc(midbuf, pict.size); |
1422 | if (!picc) goto failure; else midbuf = picc; |
||
1423 | } |
||
5 | Plagman | 1424 | |
109 | terminx | 1425 | if (dedxtfilter(fil, &pict, pic, midbuf, packbuf, (head->flags&4)==4)) goto failure; |
5 | Plagman | 1426 | |
109 | terminx | 1427 | bglCompressedTexImage2DARB(GL_TEXTURE_2D,level,pict.format,pict.xdim,pict.ydim,pict.border, |
1428 | pict.size,pic); |
||
1429 | if (bglGetError() != GL_NO_ERROR) goto failure; |
||
614 | terminx | 1430 | |
1431 | { |
||
1432 | GLint format; |
||
1433 | bglGetTexLevelParameteriv(GL_TEXTURE_2D, level, GL_TEXTURE_INTERNAL_FORMAT, &format); |
||
1434 | if (bglGetError() != GL_NO_ERROR) goto failure; |
||
1435 | format = B_LITTLE32(format); |
||
1436 | if (pict.format != format) |
||
1437 | { |
||
1438 | initprintf("invalid texture cache file format %d %d\n",pict.format, format); |
||
1439 | goto failure; |
||
1440 | } |
||
1441 | } |
||
1442 | |||
109 | terminx | 1443 | } |
5 | Plagman | 1444 | |
109 | terminx | 1445 | if (midbuf) free(midbuf); |
1446 | if (pic) free(pic); |
||
1447 | if (packbuf) free(packbuf); |
||
1448 | return 0; |
||
5 | Plagman | 1449 | failure: |
109 | terminx | 1450 | if (midbuf) free(midbuf); |
1451 | if (pic) free(pic); |
||
1452 | if (packbuf) free(packbuf); |
||
1453 | return -1; |
||
5 | Plagman | 1454 | } |
1455 | // --------------------------------------------------- JONOF'S COMPRESSED TEXTURE CACHE STUFF |
||
723 | terminx | 1456 | static void applypalmapsT(char *pic, int sizx, int sizy, int dapic,int dapalnum, int dameth) |
587 | terminx | 1457 | { |
1458 | //_initprintf("%d\n",pal); |
||
1459 | int stage; |
||
723 | terminx | 1460 | pthtyp *pichead1=pichead; |
1461 | |||
587 | terminx | 1462 | for (stage=0;stage<MAXPALCONV;stage++) |
1463 | { |
||
723 | terminx | 1464 | int pal1=0,pal2=dapalnum; |
589 | plagman | 1465 | pthtyp *pth; |
723 | terminx | 1466 | getpalmap(&stage,&pal1,&pal2); |
587 | terminx | 1467 | if (!pal1)return; |
5 | Plagman | 1468 | |
723 | terminx | 1469 | //_initprintf("Pal: %d\n",pal1); |
1470 | if (hicfindsubst(dapic, pal1, 0)) |
||
1471 | gltexcache(dapic, pal1, dameth); |
||
1472 | for (pth=pichead1; pth; pth=pth->next) |
||
587 | terminx | 1473 | if (pth->palnum ==pal1&&pth->palmap)break; |
1474 | if (!pth||pth->size!=sizx*sizy)continue; |
||
1475 | |||
1476 | applypalmap(pic,pth->palmap,pth->size,pal2); |
||
1477 | } |
||
1478 | } |
||
1479 | |||
1480 | int gloadtile_hi(int dapic,int dapalnum, int facen, hicreplctyp *hicr, int dameth, pthtyp *pth, int doalloc, char effect) |
||
5 | Plagman | 1481 | { |
109 | terminx | 1482 | coltype *pic = NULL, *rpptr; |
654 | terminx | 1483 | int j, x, y, xsiz=0, ysiz=0, tsizx, tsizy; |
665 | terminx | 1484 | int r, g, b; |
5 | Plagman | 1485 | |
109 | terminx | 1486 | char *picfil = NULL, *fn, hasalpha = 255; |
584 | terminx | 1487 | int picfillen, texfmt = GL_RGBA, intexfmt = GL_RGBA, filh; |
5 | Plagman | 1488 | |
584 | terminx | 1489 | int cachefil = -1; |
109 | terminx | 1490 | texcacheheader cachead; |
5 | Plagman | 1491 | |
109 | terminx | 1492 | if (!hicr) return -1; |
584 | terminx | 1493 | if (facen > 0) |
1494 | { |
||
109 | terminx | 1495 | if (!hicr->skybox) return -1; |
1496 | if (facen > 6) return -1; |
||
1497 | if (!hicr->skybox->face[facen-1]) return -1; |
||
1498 | fn = hicr->skybox->face[facen-1]; |
||
584 | terminx | 1499 | } |
1500 | else |
||
1501 | { |
||
109 | terminx | 1502 | if (!hicr->filename) return -1; |
1503 | fn = hicr->filename; |
||
1504 | } |
||
5 | Plagman | 1505 | |
584 | terminx | 1506 | if ((filh = kopen4load(fn, 0)) < 0) |
1507 | { |
||
109 | terminx | 1508 | initprintf("hightile: %s (pic %d) not found\n", fn, dapic); |
1509 | if (facen > 0) |
||
1510 | hicr->skybox->ignore = 1; |
||
1511 | else |
||
1512 | hicr->ignore = 1; |
||
1513 | return -1; |
||
1514 | } |
||
1515 | picfillen = kfilelength(filh); |
||
5 | Plagman | 1516 | |
109 | terminx | 1517 | kclose(filh); // FIXME: shouldn't have to do this. bug in cache1d.c |
5 | Plagman | 1518 | |
587 | terminx | 1519 | cachefil = trytexcache(fn, picfillen+(dapalnum<<8), dameth, effect, &cachead); |
1520 | if (cachefil >= 0 && !gloadtile_cached(cachefil, &cachead, &doalloc, pth, dapalnum)) |
||
584 | terminx | 1521 | { |
109 | terminx | 1522 | tsizx = cachead.xdim; |
1523 | tsizy = cachead.ydim; |
||
1524 | hasalpha = (cachead.flags & 2) ? 0 : 255; |
||
1525 | kclose(cachefil); |
||
1526 | //kclose(filh); // FIXME: uncomment when cache1d.c is fixed |
||
1527 | // cachefil >= 0, so it won't be rewritten |
||
584 | terminx | 1528 | } |
1529 | else |
||
1530 | { |
||
109 | terminx | 1531 | if (cachefil >= 0) kclose(cachefil); |
1532 | cachefil = -1; // the compressed version will be saved to disk |
||
5 | Plagman | 1533 | |
109 | terminx | 1534 | if ((filh = kopen4load(fn, 0)) < 0) return -1; |
5 | Plagman | 1535 | |
584 | terminx | 1536 | picfil = (char *)malloc(picfillen); if (!picfil) { kclose(filh); return 1; } |
109 | terminx | 1537 | kread(filh, picfil, picfillen); |
1538 | kclose(filh); |
||
5 | Plagman | 1539 | |
109 | terminx | 1540 | // tsizx/y = replacement texture's natural size |
1541 | // xsiz/y = 2^x size of replacement |
||
5 | Plagman | 1542 | |
109 | terminx | 1543 | kpgetdim(picfil,picfillen,&tsizx,&tsizy); |
1544 | if (tsizx == 0 || tsizy == 0) { free(picfil); return -1; } |
||
1545 | pth->sizx = tsizx; |
||
1546 | pth->sizy = tsizy; |
||
5 | Plagman | 1547 | |
584 | terminx | 1548 | if (!glinfo.texnpot) |
1549 | { |
||
331 | terminx | 1550 | for (xsiz=1;xsiz<tsizx;xsiz+=xsiz); |
1551 | for (ysiz=1;ysiz<tsizy;ysiz+=ysiz); |
||
584 | terminx | 1552 | } |
1553 | else |
||
1554 | { |
||
109 | terminx | 1555 | xsiz = tsizx; |
1556 | ysiz = tsizy; |
||
1557 | } |
||
1558 | pic = (coltype *)calloc(xsiz,ysiz*sizeof(coltype)); if (!pic) { free(picfil); return 1; } |
||
5 | Plagman | 1559 | |
737 | qbix79 | 1560 | if (kprender(picfil,picfillen,(intptr_t)pic,xsiz*sizeof(coltype),xsiz,ysiz,0,0)) { free(picfil); free(pic); return -2; } |
723 | terminx | 1561 | applypalmapsT((char *)pic,tsizx,tsizy,dapic,dapalnum,dameth); |
665 | terminx | 1562 | |
1563 | r=(glinfo.bgra)?hictinting[dapalnum].r:hictinting[dapalnum].b; |
||
1564 | g=hictinting[dapalnum].g; |
||
1565 | b=(glinfo.bgra)?hictinting[dapalnum].b:hictinting[dapalnum].r; |
||
331 | terminx | 1566 | for (y=0,j=0;y<tsizy;y++,j+=xsiz) |
109 | terminx | 1567 | { |
1568 | coltype tcol; |
||
1569 | char *cptr = &britable[gammabrightness ? 0 : curbrightness][0]; |
||
1570 | rpptr = &pic[j]; |
||
5 | Plagman | 1571 | |
331 | terminx | 1572 | for (x=0;x<tsizx;x++) |
109 | terminx | 1573 | { |
1574 | tcol.b = cptr[rpptr[x].b]; |
||
1575 | tcol.g = cptr[rpptr[x].g]; |
||
1576 | tcol.r = cptr[rpptr[x].r]; |
||
1577 | tcol.a = rpptr[x].a; hasalpha &= rpptr[x].a; |
||
5 | Plagman | 1578 | |
584 | terminx | 1579 | if (effect & 1) |
1580 | { |
||
109 | terminx | 1581 | // greyscale |
1582 | tcol.b = max(tcol.b, max(tcol.g, tcol.r)); |
||
1583 | tcol.g = tcol.r = tcol.b; |
||
1584 | } |
||
584 | terminx | 1585 | if (effect & 2) |
1586 | { |
||
109 | terminx | 1587 | // invert |
1588 | tcol.b = 255-tcol.b; |
||
1589 | tcol.g = 255-tcol.g; |
||
1590 | tcol.r = 255-tcol.r; |
||
1591 | } |
||
665 | terminx | 1592 | if (effect & 4) |
1593 | { |
||
1594 | // colorize |
||
1595 | tcol.b = min((int)((tcol.b)*r)/64,255); |
||
1596 | tcol.g = min((int)((tcol.g)*g)/64,255); |
||
1597 | tcol.r = min((int)((tcol.r)*b)/64,255); |
||
1598 | } |
||
5 | Plagman | 1599 | |
109 | terminx | 1600 | rpptr[x].b = tcol.b; |
1601 | rpptr[x].g = tcol.g; |
||
1602 | rpptr[x].r = tcol.r; |
||
1603 | rpptr[x].a = tcol.a; |
||
1604 | } |
||
1605 | } |
||
1606 | if ((!(dameth&4)) || (facen)) //Duplicate texture pixels (wrapping tricks for non power of 2 texture sizes) |
||
1607 | { |
||
1608 | if (xsiz > tsizx) //Copy left to right |
||
1609 | { |
||
584 | terminx | 1610 | int *lptr = (int *)pic; |
331 | terminx | 1611 | for (y=0;y<tsizy;y++,lptr+=xsiz) |
109 | terminx | 1612 | memcpy(&lptr[tsizx],lptr,(xsiz-tsizx)<<2); |
1613 | } |
||
1614 | if (ysiz > tsizy) //Copy top to bottom |
||
1615 | memcpy(&pic[xsiz*tsizy],pic,(ysiz-tsizy)*xsiz<<2); |
||
1616 | } |
||
584 | terminx | 1617 | if (!glinfo.bgra) |
1618 | { |
||
1619 | for (j=xsiz*ysiz-1;j>=0;j--) |
||
1620 | { |
||
109 | terminx | 1621 | swapchar(&pic[j].r, &pic[j].b); |
1622 | } |
||
584 | terminx | 1623 | } |
1624 | else texfmt = GL_BGRA; |
||
109 | terminx | 1625 | free(picfil); picfil = 0; |
5 | Plagman | 1626 | |
109 | terminx | 1627 | if (glinfo.texcompr && glusetexcompr && !(hicr->flags & 1)) |
1628 | intexfmt = (hasalpha == 255) ? GL_COMPRESSED_RGB_ARB : GL_COMPRESSED_RGBA_ARB; |
||
1629 | else if (hasalpha == 255) intexfmt = GL_RGB; |
||
5 | Plagman | 1630 | |
109 | terminx | 1631 | if ((doalloc&3)==1) bglGenTextures(1,(GLuint*)&pth->glpic); //# of textures (make OpenGL allocate structure) |
1632 | bglBindTexture(GL_TEXTURE_2D,pth->glpic); |
||
5 | Plagman | 1633 | |
587 | terminx | 1634 | if (dapalnum>=SPECPAL&&dapalnum<=REDPAL) |
1635 | { |
||
1636 | //_initprintf("%cLoaded palamp %d(%dx%d)",pth->palmap?'+':'-',dapalnum,xsiz,ysiz); |
||
1637 | if (!pth->palmap) |
||
1638 | { |
||
1639 | pth->size=xsiz*ysiz; |
||
1640 | pth->palmap=malloc(pth->size*4); |
||
1641 | memcpy(pth->palmap,pic,pth->size*4); |
||
1642 | } |
||
1643 | cachefil=0; |
||
1644 | } |
||
109 | terminx | 1645 | fixtransparency(pic,tsizx,tsizy,xsiz,ysiz,dameth); |
1646 | uploadtexture(doalloc,xsiz,ysiz,intexfmt,texfmt,pic,-1,tsizy,dameth); |
||
1647 | } |
||
5 | Plagman | 1648 | |
109 | terminx | 1649 | // precalculate scaling parameters for replacement |
584 | terminx | 1650 | if (facen > 0) |
1651 | { |
||
109 | terminx | 1652 | pth->scalex = ((float)tsizx) / 64.0; |
1653 | pth->scaley = ((float)tsizy) / 64.0; |
||
584 | terminx | 1654 | } |
1655 | else |
||
1656 | { |
||
109 | terminx | 1657 | pth->scalex = ((float)tsizx) / ((float)tilesizx[dapic]); |
1658 | pth->scaley = ((float)tsizy) / ((float)tilesizy[dapic]); |
||
1659 | } |
||
5 | Plagman | 1660 | |
109 | terminx | 1661 | if (gltexfiltermode < 0) gltexfiltermode = 0; |
584 | terminx | 1662 | else if (gltexfiltermode >= (int)numglfiltermodes) gltexfiltermode = numglfiltermodes-1; |
109 | terminx | 1663 | bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,glfiltermodes[gltexfiltermode].mag); |
1664 | bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,glfiltermodes[gltexfiltermode].min); |
||
5 | Plagman | 1665 | |
109 | terminx | 1666 | if (glinfo.maxanisotropy > 1.0) |
1667 | { |
||
584 | terminx | 1668 | if (glanisotropy <= 0 || glanisotropy > glinfo.maxanisotropy) glanisotropy = (int)glinfo.maxanisotropy; |
109 | terminx | 1669 | bglTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAX_ANISOTROPY_EXT,glanisotropy); |
1670 | } |
||
5 | Plagman | 1671 | |
109 | terminx | 1672 | if (!(dameth&4)) |
1673 | { |
||
1674 | bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT); |
||
1675 | bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT); |
||
1676 | } |
||
1677 | else |
||
584 | terminx | 1678 | { |
1679 | //For sprite textures, clamping looks better than wrapping |
||
109 | terminx | 1680 | bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,glinfo.clamptoedge?GL_CLAMP_TO_EDGE:GL_CLAMP); |
1681 | bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,glinfo.clamptoedge?GL_CLAMP_TO_EDGE:GL_CLAMP); |
||
1682 | } |
||
5 | Plagman | 1683 | |
109 | terminx | 1684 | if (pic) free(pic); |
1685 | |||
1686 | pth->picnum = dapic; |
||
1687 | pth->effects = effect; |
||
1688 | pth->flags = ((dameth&4)>>2) + 2 + ((facen>0)<<2); if (hasalpha != 255) pth->flags |= 8; |
||
1689 | pth->skyface = facen; |
||
1690 | pth->hicr = hicr; |
||
1691 | |||
584 | terminx | 1692 | if (cachefil < 0) |
1693 | { |
||
109 | terminx | 1694 | // save off the compressed version |
1695 | cachead.xdim = tsizx; |
||
1696 | cachead.ydim = tsizy; |
||
1697 | x = 0; |
||
584 | terminx | 1698 | for (j=0;j<31;j++) |
1699 | { |
||
109 | terminx | 1700 | if (xsiz == pow2long[j]) { x |= 1; } |
1701 | if (ysiz == pow2long[j]) { x |= 2; } |
||
1702 | } |
||
1703 | cachead.flags = (x!=3) | (hasalpha != 255 ? 2 : 0); |
||
710 | terminx | 1704 | initprintf("No cached tex for tile %d pal %d. ",dapic,dapalnum); |
587 | terminx | 1705 | writexcache(fn, picfillen+(dapalnum<<8), dameth, effect, &cachead); |
109 | terminx | 1706 | } |
1707 | |||
1708 | return 0; |
||
5 | Plagman | 1709 | } |
1710 | |||
1711 | #endif |
||
1712 | |||
109 | terminx | 1713 | //(dpx,dpy) specifies an n-sided polygon. The polygon must be a convex clockwise loop. |
1714 | // n must be <= 8 (assume clipping can double number of vertices) |
||
1715 | //method: 0:solid, 1:masked(255 is transparent), 2:transluscent #1, 3:transluscent #2 |
||
1716 | // +4 means it's a sprite, so wraparound isn't needed |
||
584 | terminx | 1717 | static int pow2xsplit = 0, skyclamphack = 0; |
5 | Plagman | 1718 | |
584 | terminx | 1719 | void drawpoly(double *dpx, double *dpy, int n, int method) |
5 | Plagman | 1720 | { |
331 | terminx | 1721 | #define PI 3.14159265358979323 |
109 | terminx | 1722 | double ngdx = 0.0, ngdy = 0.0, ngdo = 0.0, ngux = 0.0, nguy = 0.0, nguo = 0.0; |
1723 | double ngvx = 0.0, ngvy = 0.0, ngvo = 0.0, dp, up, vp, rdp, du0 = 0.0, du1 = 0.0, dui, duj; |
||
1724 | double ngdx2, ngux2, ngvx2; |
||
1725 | double f, r, ox, oy, oz, ox2, oy2, oz2, dd[16], uu[16], vv[16], px[16], py[16], uoffs; |
||
584 | terminx | 1726 | int i, j, k, x, y, z, nn, ix0, ix1, mini, maxi, tsizx, tsizy, tsizxm1 = 0, tsizym1 = 0, ltsizy = 0; |
1727 | int xx, yy, xi, d0, u0, v0, d1, u1, v1, xmodnice = 0, ymulnice = 0, dorot; |
||
109 | terminx | 1728 | char dacol = 0, *walptr, *palptr = NULL, *vidp, *vide; |
5 | Plagman | 1729 | #ifdef USE_OPENGL |
654 | terminx | 1730 | pthtyp *pth, *detailpth, *glowpth; |
497 | Plagman | 1731 | int texunits = GL_TEXTURE0_ARB; |
5 | Plagman | 1732 | #endif |
248 | terminx | 1733 | // backup of the n for possible redrawing of fullbright |
584 | terminx | 1734 | int n_ = n, method_ = method; |
5 | Plagman | 1735 | |
109 | terminx | 1736 | if (method == -1) return; |
5 | Plagman | 1737 | |
109 | terminx | 1738 | if (n == 3) |
1739 | { |
||
1740 | if ((dpx[0]-dpx[1])*(dpy[2]-dpy[1]) >= (dpx[2]-dpx[1])*(dpy[0]-dpy[1])) return; //for triangle |
||
1741 | } |
||
1742 | else |
||
1743 | { |
||
1744 | f = 0; //f is area of polygon / 2 |
||
331 | terminx | 1745 | for (i=n-2,j=n-1,k=0;k<n;i=j,j=k,k++) f += (dpx[i]-dpx[k])*dpy[j]; |
109 | terminx | 1746 | if (f <= 0) return; |
1747 | } |
||
5 | Plagman | 1748 | |
109 | terminx | 1749 | //Load texture (globalpicnum) |
584 | terminx | 1750 | if ((unsigned int)globalpicnum >= MAXTILES) globalpicnum = 0; |
109 | terminx | 1751 | setgotpic(globalpicnum); |
1752 | tsizx = tilesizx[globalpicnum]; |
||
1753 | tsizy = tilesizy[globalpicnum]; |
||
355 | terminx | 1754 | if (palookup[globalpal] == NULL) |
1755 | globalpal = 0; |
||
109 | terminx | 1756 | if (!waloff[globalpicnum]) |
1757 | { |
||
1758 | loadtile(globalpicnum); |
||
1759 | if (!waloff[globalpicnum]) |
||
1760 | { |
||
278 | Plagman | 1761 | if (rendmode < 3) return; |
109 | terminx | 1762 | tsizx = tsizy = 1; method = 1; //Hack to update Z-buffer for invalid mirror textures |
1763 | } |
||
1764 | } |
||
1765 | walptr = (char *)waloff[globalpicnum]; |
||
5 | Plagman | 1766 | |
109 | terminx | 1767 | j = 0; dorot = ((gchang != 1.0) || (gctang != 1.0)); |
1768 | if (dorot) |
||
1769 | { |
||
331 | terminx | 1770 | for (i=0;i<n;i++) |
109 | terminx | 1771 | { |
1772 | ox = dpx[i]-ghalfx; |
||
1773 | oy = dpy[i]-ghoriz; |
||
1774 | oz = ghalfx; |
||
5 | Plagman | 1775 | |
109 | terminx | 1776 | //Up/down rotation |
1777 | ox2 = ox; |
||
1778 | oy2 = oy*gchang - oz*gshang; |
||
1779 | oz2 = oy*gshang + oz*gchang; |
||
5 | Plagman | 1780 | |
109 | terminx | 1781 | //Tilt rotation |
1782 | ox = ox2*gctang - oy2*gstang; |
||
1783 | oy = ox2*gstang + oy2*gctang; |
||
1784 | oz = oz2; |
||
5 | Plagman | 1785 | |
278 | Plagman | 1786 | if ((oz < SCISDIST) && (rendmode < 3)) return; //annoying hack to avoid bugs in software rendering |
5 | Plagman | 1787 | |
109 | terminx | 1788 | r = ghalfx / oz; |
5 | Plagman | 1789 | |
109 | terminx | 1790 | dd[j] = (dpx[i]*gdx + dpy[i]*gdy + gdo)*r; |
1791 | uu[j] = (dpx[i]*gux + dpy[i]*guy + guo)*r; |
||
1792 | vv[j] = (dpx[i]*gvx + dpy[i]*gvy + gvo)*r; |
||
5 | Plagman | 1793 | |
109 | terminx | 1794 | px[j] = ox*r + ghalfx; |
1795 | py[j] = oy*r + ghoriz; |
||
1796 | if ((!j) || (px[j] != px[j-1]) || (py[j] != py[j-1])) j++; |
||
1797 | } |
||
1798 | } |
||
1799 | else |
||
1800 | { |
||
331 | terminx | 1801 | for (i=0;i<n;i++) |
109 | terminx | 1802 | { |
1803 | px[j] = dpx[i]; |
||
1804 | py[j] = dpy[i]; |
||
1805 | if ((!j) || (px[j] != px[j-1]) || (py[j] != py[j-1])) j++; |
||
1806 | } |
||
1807 | } |
||
1808 | while ((j >= 3) && (px[j-1] == px[0]) && (py[j-1] == py[0])) j--; |
||
1809 | if (j < 3) return; |
||
1810 | n = j; |
||
5 | Plagman | 1811 | |
1812 | #ifdef USE_OPENGL |
||
278 | Plagman | 1813 | if (rendmode >= 3) |
109 | terminx | 1814 | { |
1815 | float hackscx, hackscy; |
||
5 | Plagman | 1816 | |
109 | terminx | 1817 | if (skyclamphack) method |= 4; |
1818 | pth = gltexcache(globalpicnum,globalpal,method&(~3)); |
||
244 | Plagman | 1819 | |
886 | terminx | 1820 | if (r_fullbrights && pth->flags & 16) |
248 | terminx | 1821 | if (indrawroomsandmasks) |
1822 | { |
||
1823 | if (!fullbrightdrawingpass) |
||
1824 | fullbrightdrawingpass = 1; |
||
1825 | else if (fullbrightdrawingpass == 2) |
||
1826 | pth = pth->ofb; |
||
1827 | } |
||
244 | Plagman | 1828 | |
109 | terminx | 1829 | bglBindTexture(GL_TEXTURE_2D, pth ? pth->glpic : 0); |
5 | Plagman | 1830 | |
590 | plagman | 1831 | if (srepeat) |
1832 | bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT); |
||
1833 | if (trepeat) |
||
1834 | bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT); |
||
1835 | |||
504 | Plagman | 1836 | // texture scale by parkar request |
506 | terminx | 1837 | if (pth && pth->hicr && ((pth->hicr->xscale != 1.0f) || (pth->hicr->yscale != 1.0f)) && !drawingskybox) |
504 | Plagman | 1838 | { |
1839 | bglMatrixMode(GL_TEXTURE); |
||
1840 | bglLoadIdentity(); |
||
1841 | bglScalef(pth->hicr->xscale, pth->hicr->yscale, 1.0f); |
||
1842 | bglMatrixMode(GL_MODELVIEW); |
||
1843 | } |
||
1844 | |||
1845 | // detail texture |
||
459 | Plagman | 1846 | detailpth = NULL; |
503 | Plagman | 1847 | if (r_detailmapping && usehightile && !r_depthpeeling && !drawingskybox && |
584 | terminx | 1848 | hicfindsubst(globalpicnum, DETAILPAL, 0)) |
497 | Plagman | 1849 | detailpth = gltexcache(globalpicnum, DETAILPAL, method&(~3)); |
459 | Plagman | 1850 | |
1851 | if (detailpth && (detailpth->hicr->palnum == DETAILPAL)) |
||
1852 | { |
||
497 | Plagman | 1853 | bglActiveTextureARB(++texunits); |
459 | Plagman | 1854 | |
1855 | bglEnable(GL_TEXTURE_2D); |
||
1856 | bglBindTexture(GL_TEXTURE_2D, detailpth ? detailpth->glpic : 0); |
||
1857 | |||
497 | Plagman | 1858 | bglTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB); |
459 | Plagman | 1859 | bglTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE); |
1860 | |||
497 | Plagman | 1861 | bglTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS_ARB); |
1862 | bglTexEnvf(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR); |
||
459 | Plagman | 1863 | |
497 | Plagman | 1864 | bglTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE); |
1865 | bglTexEnvf(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR); |
||
584 | terminx | 1866 | |
459 | Plagman | 1867 | bglTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE); |
497 | Plagman | 1868 | bglTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PREVIOUS_ARB); |
1869 | bglTexEnvf(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA); |
||
459 | Plagman | 1870 | |
497 | Plagman | 1871 | bglTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 2.0f); |
1872 | |||
459 | Plagman | 1873 | bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT); |
1874 | bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT); |
||
1875 | |||
1876 | |||
504 | Plagman | 1877 | f = detailpth ? detailpth->hicr->xscale : 1.0; |
459 | Plagman | 1878 | |
497 | Plagman | 1879 | bglMatrixMode(GL_TEXTURE); |
1880 | bglLoadIdentity(); |
||
512 | Plagman | 1881 | |
1882 | if (pth && pth->hicr && ((pth->hicr->xscale != 1.0f) || (pth->hicr->yscale != 1.0f))) |
||
1883 | bglScalef(pth->hicr->xscale, pth->hicr->yscale, 1.0f); |
||
1884 | |||
1885 | if (detailpth && detailpth->hicr && ((detailpth->hicr->xscale != 1.0f) || (detailpth->hicr->yscale != 1.0f))) |
||
1886 | bglScalef(detailpth->hicr->xscale, detailpth->hicr->yscale, 1.0f); |
||
1887 | |||
497 | Plagman | 1888 | bglMatrixMode(GL_MODELVIEW); |
459 | Plagman | 1889 | } |
1890 | |||
504 | Plagman | 1891 | // glow texture |
497 | Plagman | 1892 | glowpth = NULL; |
503 | Plagman | 1893 | if (r_glowmapping && usehightile && !r_depthpeeling && !drawingskybox && |
584 | terminx | 1894 | hicfindsubst(globalpicnum, GLOWPAL, 0)) |
497 | Plagman | 1895 | glowpth = gltexcache(globalpicnum, GLOWPAL, method&(~3)); |
1896 | |||
1897 | if (glowpth && (glowpth->hicr->palnum == GLOWPAL)) |
||
1898 | { |
||
1899 | bglActiveTextureARB(++texunits); |
||
1900 | |||
1901 | bglEnable(GL_TEXTURE_2D); |
||
1902 | bglBindTexture(GL_TEXTURE_2D, glowpth ? glowpth->glpic : 0); |
||
1903 | |||
1904 | bglTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB); |
||
1905 | bglTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_INTERPOLATE_ARB); |
||
1906 | |||
1907 | bglTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS_ARB); |
||
1908 | bglTexEnvf(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR); |
||
1909 | |||
1910 | bglTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE); |
||
1911 | bglTexEnvf(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR); |
||
1912 | |||
1913 | bglTexEnvf(GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_TEXTURE); |
||
1914 | bglTexEnvf(GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, GL_ONE_MINUS_SRC_ALPHA); |
||
1915 | |||
1916 | bglTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE); |
||
1917 | bglTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PREVIOUS_ARB); |
||
1918 | bglTexEnvf(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA); |
||
1919 | |||
1920 | bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT); |
||
1921 | bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT); |
||
1922 | } |
||
1923 | |||
109 | terminx | 1924 | if (pth && (pth->flags & 2)) |
1925 | { |
||
1926 | hackscx = pth->scalex; |
||
1927 | hackscy = pth->scaley; |
||
1928 | tsizx = pth->sizx; |
||
1929 | tsizy = pth->sizy; |
||
1930 | } |
||
1931 | else { hackscx = 1.0; hackscy = 1.0; } |
||
5 | Plagman | 1932 | |
584 | terminx | 1933 | if (!glinfo.texnpot) |
1934 | { |
||
331 | terminx | 1935 | for (xx=1;xx<tsizx;xx+=xx); ox2 = (double)1.0/(double)xx; |
1936 | for (yy=1;yy<tsizy;yy+=yy); oy2 = (double)1.0/(double)yy; |
||
584 | terminx | 1937 | } |
1938 | else |
||
1939 | { |
||
109 | terminx | 1940 | xx = tsizx; ox2 = (double)1.0/(double)xx; |
1941 | yy = tsizy; oy2 = (double)1.0/(double)yy; |
||
1942 | } |
||
5 | Plagman | 1943 | |
584 | terminx | 1944 | if ((!(method&3)) && (!fullbrightdrawingpass)) |
1945 | { |
||
475 | Plagman | 1946 | bglDisable(GL_BLEND); |
439 | Plagman | 1947 | if (!peelcompiling) |
1948 | bglDisable(GL_ALPHA_TEST); |
||
584 | terminx | 1949 | } |
1950 | else |
||
1951 | { |
||
109 | terminx | 1952 | float al = 0.0; // PLAG : default alphacut was 0.32 before goodalpha |
1953 | if (pth && pth->hicr && pth->hicr->alphacut >= 0.0) al = pth->hicr->alphacut; |
||
1954 | if (alphahackarray[globalpicnum]) |
||
1955 | al=alphahackarray[globalpicnum]; |
||
1956 | if (!waloff[globalpicnum]) al = 0.0; // invalid textures ignore the alpha cutoff settings |
||
439 | Plagman | 1957 | if (!peelcompiling) |
1958 | bglEnable(GL_BLEND); |
||
109 | terminx | 1959 | bglEnable(GL_ALPHA_TEST); |
1960 | bglAlphaFunc(GL_GREATER,al); |
||
1961 | } |
||
5 | Plagman | 1962 | |
109 | terminx | 1963 | if (!dorot) |
1964 | { |
||
331 | terminx | 1965 | for (i=n-1;i>=0;i--) |
109 | terminx | 1966 | { |
1967 | dd[i] = px[i]*gdx + py[i]*gdy + gdo; |
||
1968 | uu[i] = px[i]*gux + py[i]*guy + guo; |
||
1969 | vv[i] = px[i]*gvx + py[i]*gvy + gvo; |
||
1970 | } |
||
1971 | } |
||
5 | Plagman | 1972 | |
109 | terminx | 1973 | { |
1974 | float pc[4]; |
||
379 | terminx | 1975 | f = ((float)(numpalookups-min(max(globalshade * shadescale,0),numpalookups)))/((float)numpalookups); |
109 | terminx | 1976 | pc[0] = pc[1] = pc[2] = f; |
331 | terminx | 1977 | switch (method&3) |
109 | terminx | 1978 | { |
347 | terminx | 1979 | default: |
331 | terminx | 1980 | case 0: |
1981 | pc[3] = 1.0; break; |
||
1982 | case 1: |
||
1983 | pc[3] = 1.0; break; |
||
1984 | case 2: |
||
1985 | pc[3] = 0.66; break; |
||
1986 | case 3: |
||
1987 | pc[3] = 0.33; break; |
||
109 | terminx | 1988 | } |
1989 | // tinting happens only to hightile textures, and only if the texture we're |
||
1990 | // rendering isn't for the same palette as what we asked for |
||
665 | terminx | 1991 | if (!(hictinting[globalpal].f&4)) |
708 | terminx | 1992 | if (pth && (pth->flags & 2)) |
384 | terminx | 1993 | { |
708 | terminx | 1994 | if (pth->palnum != globalpal) |
1995 | { |
||
1996 | // apply tinting for replaced textures |
||
1997 | pc[0] *= (float)hictinting[globalpal].r / 255.0; |
||
1998 | pc[1] *= (float)hictinting[globalpal].g / 255.0; |
||
1999 | pc[2] *= (float)hictinting[globalpal].b / 255.0; |
||
2000 | } |
||
2001 | if (hictinting[MAXPALOOKUPS-1].r != 255 || hictinting[MAXPALOOKUPS-1].g != 255 || hictinting[MAXPALOOKUPS-1].b != 255) |
||
2002 | { |
||
2003 | pc[0] *= (float)hictinting[MAXPALOOKUPS-1].r / 255.0; |
||
2004 | pc[1] *= (float)hictinting[MAXPALOOKUPS-1].g / 255.0; |
||
2005 | pc[2] *= (float)hictinting[MAXPALOOKUPS-1].b / 255.0; |
||
2006 | } |
||
384 | terminx | 2007 | } |
2008 | |||
109 | terminx | 2009 | bglColor4f(pc[0],pc[1],pc[2],pc[3]); |
2010 | } |
||
5 | Plagman | 2011 | |
109 | terminx | 2012 | //Hack for walls&masked walls which use textures that are not a power of 2 |
2013 | if ((pow2xsplit) && (tsizx != xx)) |
||
2014 | { |
||
2015 | if (!dorot) |
||
2016 | { |
||
2017 | ngdx = gdx; ngdy = gdy; ngdo = gdo+(ngdx+ngdy)*.5; |
||
2018 | ngux = gux; nguy = guy; nguo = guo+(ngux+nguy)*.5; |
||
2019 | ngvx = gvx; ngvy = gvy; ngvo = gvo+(ngvx+ngvy)*.5; |
||
2020 | } |
||
2021 | else |
||
2022 | { |
||
2023 | ox = py[1]-py[2]; oy = py[2]-py[0]; oz = py[0]-py[1]; |
||
2024 | r = 1.0 / (ox*px[0] + oy*px[1] + oz*px[2]); |
||
2025 | ngdx = (ox*dd[0] + oy*dd[1] + oz*dd[2])*r; |
||
2026 | ngux = (ox*uu[0] + oy*uu[1] + oz*uu[2])*r; |
||
2027 | ngvx = (ox*vv[0] + oy*vv[1] + oz*vv[2])*r; |
||
2028 | ox = px[2]-px[1]; oy = px[0]-px[2]; oz = px[1]-px[0]; |
||
2029 | ngdy = (ox*dd[0] + oy*dd[1] + oz*dd[2])*r; |
||
2030 | nguy = (ox*uu[0] + oy*uu[1] + oz*uu[2])*r; |
||
2031 | ngvy = (ox*vv[0] + oy*vv[1] + oz*vv[2])*r; |
||
2032 | ox = px[0]-.5; oy = py[0]-.5; //.5 centers texture nicely |
||
2033 | ngdo = dd[0] - ox*ngdx - oy*ngdy; |
||
2034 | nguo = uu[0] - ox*ngux - oy*nguy; |
||
2035 | ngvo = vv[0] - ox*ngvx - oy*ngvy; |
||
2036 | } |
||
5 | Plagman | 2037 | |
109 | terminx | 2038 | ngux *= hackscx; nguy *= hackscx; nguo *= hackscx; |
2039 | ngvx *= hackscy; ngvy *= hackscy; ngvo *= hackscy; |
||
2040 | uoffs = ((double)(xx-tsizx)*.5); |
||
2041 | ngux -= ngdx*uoffs; |
||
2042 | nguy -= ngdy*uoffs; |
||
2043 | nguo -= ngdo*uoffs; |
||
5 | Plagman | 2044 | |
109 | terminx | 2045 | //Find min&max u coordinates (du0...du1) |
331 | terminx | 2046 | for (i=0;i<n;i++) |
109 | terminx | 2047 | { |
2048 | ox = px[i]; oy = py[i]; |
||
2049 | f = (ox*ngux + oy*nguy + nguo) / (ox*ngdx + oy*ngdy + ngdo); |
||
2050 | if (!i) { du0 = du1 = f; continue; } |
||
2051 | if (f < du0) du0 = f; |
||
2052 | else if (f > du1) du1 = f; |
||
2053 | } |
||
5 | Plagman | 2054 | |
109 | terminx | 2055 | f = 1.0/(double)tsizx; |
584 | terminx | 2056 | ix0 = (int)floor(du0*f); |
2057 | ix1 = (int)floor(du1*f); |
||
331 | terminx | 2058 | for (;ix0<=ix1;ix0++) |
109 | terminx | 2059 | { |
584 | terminx | 2060 | du0 = (double)((ix0)*tsizx); // + uoffs; |
109 | terminx | 2061 | du1 = (double)((ix0+1)*tsizx); // + uoffs; |
5 | Plagman | 2062 | |
109 | terminx | 2063 | i = 0; nn = 0; |
2064 | duj = (px[i]*ngux + py[i]*nguy + nguo) / (px[i]*ngdx + py[i]*ngdy + ngdo); |
||
2065 | do |
||
2066 | { |
||
2067 | j = i+1; if (j == n) j = 0; |
||
5 | Plagman | 2068 | |
109 | terminx | 2069 | dui = duj; duj = (px[j]*ngux + py[j]*nguy + nguo) / (px[j]*ngdx + py[j]*ngdy + ngdo); |
5 | Plagman | 2070 | |
584 | terminx | 2071 | if ((du0 <= dui) && (dui <= du1)) { uu[nn] = px[i]; vv[nn] = py[i]; nn++; } |
109 | terminx | 2072 | if (duj <= dui) |
2073 | { |
||
2074 | if ((du1 < duj) != (du1 < dui)) |
||
2075 | { |
||
2076 | //ox*(ngux-ngdx*du1) + oy*(nguy-ngdy*du1) + (nguo-ngdo*du1) = 0 |
||
2077 | //(px[j]-px[i])*f + px[i] = ox |
||
2078 | //(py[j]-py[i])*f + py[i] = oy |
||
5 | Plagman | 2079 | |
109 | terminx | 2080 | ///Solve for f |
2081 | //((px[j]-px[i])*f + px[i])*(ngux-ngdx*du1) + |
||
2082 | //((py[j]-py[i])*f + py[i])*(nguy-ngdy*du1) + (nguo-ngdo*du1) = 0 |
||
5 | Plagman | 2083 | |
584 | terminx | 2084 | f = -(px[i] *(ngux-ngdx*du1) + py[i] *(nguy-ngdy*du1) + (nguo-ngdo*du1)) / |
109 | terminx | 2085 | ((px[j]-px[i])*(ngux-ngdx*du1) + (py[j]-py[i])*(nguy-ngdy*du1)); |
2086 | uu[nn] = (px[j]-px[i])*f + px[i]; |
||
2087 | vv[nn] = (py[j]-py[i])*f + py[i]; nn++; |
||
2088 | } |
||
2089 | if ((du0 < duj) != (du0 < dui)) |
||
2090 | { |
||
584 | terminx | 2091 | f = -(px[i] *(ngux-ngdx*du0) + py[i] *(nguy-ngdy*du0) + (nguo-ngdo*du0)) / |
109 | terminx | 2092 | ((px[j]-px[i])*(ngux-ngdx*du0) + (py[j]-py[i])*(nguy-ngdy*du0)); |
2093 | uu[nn] = (px[j]-px[i])*f + px[i]; |
||
2094 | vv[nn] = (py[j]-py[i])*f + py[i]; nn++; |
||
2095 | } |
||
2096 | } |
||
2097 | else |
||
2098 | { |
||
2099 | if ((du0 < duj) != (du0 < dui)) |
||
2100 | { |
||
584 | terminx | 2101 | f = -(px[i] *(ngux-ngdx*du0) + py[i] *(nguy-ngdy*du0) + (nguo-ngdo*du0)) / |
109 | terminx | 2102 | ((px[j]-px[i])*(ngux-ngdx*du0) + (py[j]-py[i])*(nguy-ngdy*du0)); |
2103 | uu[nn] = (px[j]-px[i])*f + px[i]; |
||
2104 | vv[nn] = (py[j]-py[i])*f + py[i]; nn++; |
||
2105 | } |
||
2106 | if ((du1 < duj) != (du1 < dui)) |
||
2107 | { |
||
584 | terminx | 2108 | f = -(px[i] *(ngux-ngdx*du1) + py[i] *(nguy-ngdy*du1) + (nguo-ngdo*du1)) / |
109 | terminx | 2109 | ((px[j]-px[i])*(ngux-ngdx*du1) + (py[j]-py[i])*(nguy-ngdy*du1)); |
2110 | uu[nn] = (px[j]-px[i])*f + px[i]; |
||
2111 | vv[nn] = (py[j]-py[i])*f + py[i]; nn++; |
||
2112 | } |
||
2113 | } |
||
2114 | i = j; |
||
584 | terminx | 2115 | } |
2116 | while (i); |
||
109 | terminx | 2117 | if (nn < 3) continue; |
5 | Plagman | 2118 | |
109 | terminx | 2119 | bglBegin(GL_TRIANGLE_FAN); |
331 | terminx | 2120 | for (i=0;i<nn;i++) |
109 | terminx | 2121 | { |
2122 | ox = uu[i]; oy = vv[i]; |
||
2123 | dp = ox*ngdx + oy*ngdy + ngdo; |
||
2124 | up = ox*ngux + oy*nguy + nguo; |
||
2125 | vp = ox*ngvx + oy*ngvy + ngvo; |
||
459 | Plagman | 2126 | r = 1.0/dp; |
497 | Plagman | 2127 | if (texunits > GL_TEXTURE0_ARB) |