]> icculus.org git repositories - taylor/freespace2.git/blob - src/graphics/gropengl1render.cpp
initial graphics system update
[taylor/freespace2.git] / src / graphics / gropengl1render.cpp
1 /*
2  * Copyright (C) Volition, Inc. 1999.  All rights reserved.
3  *
4  * All source code herein is the property of Volition, Inc. You may not sell
5  * or otherwise commercially exploit the source or things you created based on
6  * the source.
7  */
8
9 #include "pstypes.h"
10 #include "2d.h"
11 #include "gropengl.h"
12 #include "gropengl1.h"
13 #include "gropenglinternal.h"
14 #include "bmpman.h"
15 #include "grinternal.h"
16 #include "3d.h"
17 #include "neb.h"
18 #include "line.h"
19 #include "palman.h"
20
21
22 extern int OGL_fog_mode;
23
24 #define NEBULA_COLORS 20
25
26
27 static void opengl1_rect_internal(int x, int y, int w, int h, int r, int g, int b, int a)
28 {
29         int saved_zbuf;
30         vertex v[4];
31         vertex *verts[4] = {&v[0], &v[1], &v[2], &v[3]};
32
33         saved_zbuf = gr_zbuffer_get();
34
35         // start the frame, no zbuffering, no culling
36         g3_start_frame(1);
37         gr_zbuffer_set(GR_ZBUFF_NONE);
38         gr_set_cull(0);
39
40         // stuff coords
41         v[0].sx = i2fl(x);
42         v[0].sy = i2fl(y);
43         v[0].sw = 0.0f;
44         v[0].u = 0.0f;
45         v[0].v = 0.0f;
46         v[0].flags = PF_PROJECTED;
47         v[0].codes = 0;
48         v[0].r = (ubyte)r;
49         v[0].g = (ubyte)g;
50         v[0].b = (ubyte)b;
51         v[0].a = (ubyte)a;
52
53         v[1].sx = i2fl(x + w);
54         v[1].sy = i2fl(y);
55         v[1].sw = 0.0f;
56         v[1].u = 0.0f;
57         v[1].v = 0.0f;
58         v[1].flags = PF_PROJECTED;
59         v[1].codes = 0;
60         v[1].r = (ubyte)r;
61         v[1].g = (ubyte)g;
62         v[1].b = (ubyte)b;
63         v[1].a = (ubyte)a;
64
65         v[2].sx = i2fl(x + w);
66         v[2].sy = i2fl(y + h);
67         v[2].sw = 0.0f;
68         v[2].u = 0.0f;
69         v[2].v = 0.0f;
70         v[2].flags = PF_PROJECTED;
71         v[2].codes = 0;
72         v[2].r = (ubyte)r;
73         v[2].g = (ubyte)g;
74         v[2].b = (ubyte)b;
75         v[2].a = (ubyte)a;
76
77         v[3].sx = i2fl(x);
78         v[3].sy = i2fl(y + h);
79         v[3].sw = 0.0f;
80         v[3].u = 0.0f;
81         v[3].v = 0.0f;
82         v[3].flags = PF_PROJECTED;
83         v[3].codes = 0;
84         v[3].r = (ubyte)r;
85         v[3].g = (ubyte)g;
86         v[3].b = (ubyte)b;
87         v[3].a = (ubyte)a;
88
89         // draw the polys
90         g3_draw_poly_constant_sw(4, verts, TMAP_FLAG_GOURAUD | TMAP_FLAG_RGB | TMAP_FLAG_ALPHA, 0.1f);
91
92         g3_end_frame();
93
94         // restore zbuffer and culling
95         gr_zbuffer_set(saved_zbuf);
96         gr_set_cull(1);
97 }
98
99 void gr_opengl1_rect(int x,int y,int w,int h)
100 {
101         opengl1_rect_internal(x, y, w, h, gr_screen.current_color.red, gr_screen.current_color.green, gr_screen.current_color.blue, gr_screen.current_color.alpha);
102 }
103
104 void gr_opengl1_shade(int x,int y,int w,int h)
105 {
106         int r,g,b,a;
107
108         float shade1 = 1.0f;
109         float shade2 = 6.0f;
110
111         r = fl2i(gr_screen.current_shader.r*255.0f*shade1);
112         if ( r < 0 ) r = 0; else if ( r > 255 ) r = 255;
113         g = fl2i(gr_screen.current_shader.g*255.0f*shade1);
114         if ( g < 0 ) g = 0; else if ( g > 255 ) g = 255;
115         b = fl2i(gr_screen.current_shader.b*255.0f*shade1);
116         if ( b < 0 ) b = 0; else if ( b > 255 ) b = 255;
117         a = fl2i(gr_screen.current_shader.c*255.0f*shade2);
118         if ( a < 0 ) a = 0; else if ( a > 255 ) a = 255;
119
120         opengl1_rect_internal(x, y, w, h, r, g, b, a);
121 }
122
123 static void opengl1_aabitmap_ex_internal(int x,int y,int w,int h,int sx,int sy)
124 {
125         if ( w < 1 ) return;
126         if ( h < 1 ) return;
127
128         if ( !gr_screen.current_color.is_alphacolor )
129                 return;
130
131         float u_scale, v_scale;
132
133         if ( !opengl1_tcache_set( gr_screen.current_bitmap, TCACHE_TYPE_AABITMAP, &u_scale, &v_scale, 0, -1, -1, 0 ) )  {
134                 // Couldn't set texture
135                 mprintf(( "WARNING: Error setting aabitmap texture!\n" ));
136                 return;
137         }
138
139         opengl1_set_state( TEXTURE_SOURCE_NO_FILTERING, ALPHA_BLEND_ALPHA_BLEND_ALPHA, ZBUFFER_TYPE_NONE );
140
141         float u0, u1, v0, v1;
142         float x1, x2, y1, y2;
143         int bw, bh;
144
145         bm_get_info( gr_screen.current_bitmap, &bw, &bh );
146
147         u0 = u_scale*i2fl(sx)/i2fl(bw);
148         v0 = v_scale*i2fl(sy)/i2fl(bh);
149
150         u1 = u_scale*i2fl(sx+w)/i2fl(bw);
151         v1 = v_scale*i2fl(sy+h)/i2fl(bh);
152
153         x1 = i2fl(x+gr_screen.offset_x);
154         y1 = i2fl(y+gr_screen.offset_y);
155         x2 = i2fl(x+w+gr_screen.offset_x);
156         y2 = i2fl(y+h+gr_screen.offset_y);
157
158         glColor4ub(gr_screen.current_color.red, gr_screen.current_color.green,
159                         gr_screen.current_color.blue,gr_screen.current_color.alpha);
160
161         opengl_alloc_render_buffer(4);
162
163         render_buffer[0].x = x1;
164         render_buffer[0].y = y2;
165         render_buffer[0].u = u0;
166         render_buffer[0].v = v1;
167
168         render_buffer[1].x = x2;
169         render_buffer[1].y = y2;
170         render_buffer[1].u = u1;
171         render_buffer[1].v = v1;
172
173         render_buffer[2].x = x2;
174         render_buffer[2].y = y1;
175         render_buffer[2].u = u1;
176         render_buffer[2].v = v0;
177
178         render_buffer[3].x = x1;
179         render_buffer[3].y = y1;
180         render_buffer[3].u = u0;
181         render_buffer[3].v = v0;
182
183         glEnableClientState(GL_TEXTURE_COORD_ARRAY);
184         glEnableClientState(GL_VERTEX_ARRAY);
185
186         glTexCoordPointer(2, GL_FLOAT, sizeof(rb_t), &render_buffer[0].u);
187         glVertexPointer(2, GL_FLOAT, sizeof(rb_t), &render_buffer[0].x);
188
189         glDrawArrays(GL_QUADS, 0, 4);
190
191         glDisableClientState(GL_TEXTURE_COORD_ARRAY);
192         glDisableClientState(GL_VERTEX_ARRAY);
193 }
194
195 void gr_opengl1_aabitmap_ex(int x,int y,int w,int h,int sx,int sy)
196 {
197         int reclip;
198         #ifndef NDEBUG
199         int count = 0;
200         #endif
201
202         int dx1=x, dx2=x+w-1;
203         int dy1=y, dy2=y+h-1;
204
205         int bw, bh;
206         bm_get_info( gr_screen.current_bitmap, &bw, &bh, NULL );
207
208         do {
209                 reclip = 0;
210                 #ifndef NDEBUG
211                         if ( count > 1 ) Int3();
212                         count++;
213                 #endif
214
215                 if ((dx1 > gr_screen.clip_right ) || (dx2 < gr_screen.clip_left)) return;
216                 if ((dy1 > gr_screen.clip_bottom ) || (dy2 < gr_screen.clip_top)) return;
217                 if ( dx1 < gr_screen.clip_left ) { sx += gr_screen.clip_left-dx1; dx1 = gr_screen.clip_left; }
218                 if ( dy1 < gr_screen.clip_top ) { sy += gr_screen.clip_top-dy1; dy1 = gr_screen.clip_top; }
219                 if ( dx2 > gr_screen.clip_right )       { dx2 = gr_screen.clip_right; }
220                 if ( dy2 > gr_screen.clip_bottom )      { dy2 = gr_screen.clip_bottom; }
221
222                 if ( sx < 0 ) {
223                         dx1 -= sx;
224                         sx = 0;
225                         reclip = 1;
226                 }
227
228                 if ( sy < 0 ) {
229                         dy1 -= sy;
230                         sy = 0;
231                         reclip = 1;
232                 }
233
234                 w = dx2-dx1+1;
235                 h = dy2-dy1+1;
236
237                 if ( sx + w > bw ) {
238                         w = bw - sx;
239                         dx2 = dx1 + w - 1;
240                 }
241
242                 if ( sy + h > bh ) {
243                         h = bh - sy;
244                         dy2 = dy1 + h - 1;
245                 }
246
247                 if ( w < 1 ) return;            // clipped away!
248                 if ( h < 1 ) return;            // clipped away!
249
250         } while (reclip);
251
252         // Make sure clipping algorithm works
253         #ifndef NDEBUG
254                 Assert( w > 0 );
255                 Assert( h > 0 );
256                 Assert( w == (dx2-dx1+1) );
257                 Assert( h == (dy2-dy1+1) );
258                 Assert( sx >= 0 );
259                 Assert( sy >= 0 );
260                 Assert( sx+w <= bw );
261                 Assert( sy+h <= bh );
262                 Assert( dx2 >= dx1 );
263                 Assert( dy2 >= dy1 );
264                 Assert( (dx1 >= gr_screen.clip_left ) && (dx1 <= gr_screen.clip_right) );
265                 Assert( (dx2 >= gr_screen.clip_left ) && (dx2 <= gr_screen.clip_right) );
266                 Assert( (dy1 >= gr_screen.clip_top ) && (dy1 <= gr_screen.clip_bottom) );
267                 Assert( (dy2 >= gr_screen.clip_top ) && (dy2 <= gr_screen.clip_bottom) );
268         #endif
269
270         // We now have dx1,dy1 and dx2,dy2 and sx, sy all set validly within clip regions.
271         opengl1_aabitmap_ex_internal(dx1,dy1,dx2-dx1+1,dy2-dy1+1,sx,sy);
272 }
273
274 void gr_opengl1_aabitmap(int x, int y)
275 {
276         int w, h;
277
278         bm_get_info( gr_screen.current_bitmap, &w, &h, NULL );
279         int dx1=x, dx2=x+w-1;
280         int dy1=y, dy2=y+h-1;
281         int sx=0, sy=0;
282
283         if ((dx1 > gr_screen.clip_right ) || (dx2 < gr_screen.clip_left)) return;
284         if ((dy1 > gr_screen.clip_bottom ) || (dy2 < gr_screen.clip_top)) return;
285         if ( dx1 < gr_screen.clip_left ) { sx = gr_screen.clip_left-dx1; dx1 = gr_screen.clip_left; }
286         if ( dy1 < gr_screen.clip_top ) { sy = gr_screen.clip_top-dy1; dy1 = gr_screen.clip_top; }
287         if ( dx2 > gr_screen.clip_right )       { dx2 = gr_screen.clip_right; }
288         if ( dy2 > gr_screen.clip_bottom )      { dy2 = gr_screen.clip_bottom; }
289
290         if ( sx < 0 ) return;
291         if ( sy < 0 ) return;
292         if ( sx >= w ) return;
293         if ( sy >= h ) return;
294
295         // Draw bitmap bm[sx,sy] into (dx1,dy1)-(dx2,dy2)
296         gr_opengl1_aabitmap_ex(dx1,dy1,dx2-dx1+1,dy2-dy1+1,sx,sy);
297 }
298
299 void gr_opengl1_string( int sx, int sy, const char *s )
300 {
301         int width, spacing, letter;
302         int x, y;
303         int rb_offset;
304         float u_scale, v_scale;
305         float u0, u1, v0, v1;
306         float x1, x2, y1, y2;
307         int bw, bh;
308
309         if ( !Current_font )    {
310                 return;
311         }
312
313         gr_set_bitmap(Current_font->bitmap_id, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
314
315         if ( !opengl1_tcache_set( gr_screen.current_bitmap, TCACHE_TYPE_AABITMAP, &u_scale, &v_scale, 0, -1, -1, 0 ) )  {
316                 // Couldn't set texture
317                 mprintf(( "WARNING: Error setting aabitmap texture!\n" ));
318                 return;
319         }
320
321         bm_get_info( gr_screen.current_bitmap, &bw, &bh );
322
323         opengl1_set_state( TEXTURE_SOURCE_NO_FILTERING, ALPHA_BLEND_ALPHA_BLEND_ALPHA, ZBUFFER_TYPE_NONE );
324
325         opengl_alloc_render_buffer(strlen(s) * 4);
326
327         x = sx;
328         y = sy;
329
330         if (sx==0x8000) {                       //centered
331                 x = get_centered_x(s);
332         } else {
333                 x = sx;
334         }
335
336         spacing = 0;
337         rb_offset = 0;
338
339         while (*s)      {
340                 x += spacing;
341
342                 while (*s== '\n' )      {
343                         s++;
344                         y += Current_font->h;
345                         if (sx==0x8000) {                       //centered
346                                 x = get_centered_x(s);
347                         } else {
348                                 x = sx;
349                         }
350                 }
351                 if (*s == 0 ) break;
352
353                 letter = get_char_width(s[0],s[1],&width,&spacing);
354                 s++;
355
356                 //not in font, draw as space
357                 if (letter<0)   {
358                         continue;
359                 }
360
361                 int xd, yd, xc, yc;
362                 int wc, hc;
363
364                 // Check if this character is totally clipped
365                 if ( x + width < gr_screen.clip_left ) continue;
366                 if ( y + Current_font->h < gr_screen.clip_top ) continue;
367                 if ( x > gr_screen.clip_right ) continue;
368                 if ( y > gr_screen.clip_bottom ) continue;
369
370                 xd = yd = 0;
371                 if ( x < gr_screen.clip_left ) xd = gr_screen.clip_left - x;
372                 if ( y < gr_screen.clip_top ) yd = gr_screen.clip_top - y;
373                 xc = x+xd;
374                 yc = y+yd;
375
376                 wc = width - xd; hc = Current_font->h - yd;
377                 if ( xc + wc > gr_screen.clip_right ) wc = gr_screen.clip_right - xc;
378                 if ( yc + hc > gr_screen.clip_bottom ) hc = gr_screen.clip_bottom - yc;
379
380                 if ( wc < 1 ) continue;
381                 if ( hc < 1 ) continue;
382
383                 int u = Current_font->bm_u[letter];
384                 int v = Current_font->bm_v[letter];
385
386                 x1 = i2fl(xc + gr_screen.offset_x);
387                 y1 = i2fl(yc + gr_screen.offset_y);
388                 x2 = i2fl(x1 + wc);
389                 y2 = i2fl(y1 + hc);
390
391                 u0 = u_scale * (i2fl(u+xd) / bw);
392                 v0 = v_scale * (i2fl(v+yd) / bh);
393
394                 u1 = u_scale * (i2fl((u+xd)+wc) / bw);
395                 v1 = v_scale * (i2fl((v+yd)+hc) / bh);
396
397                 render_buffer[rb_offset].x = x1;
398                 render_buffer[rb_offset].y = y2;
399                 render_buffer[rb_offset].u = u0;
400                 render_buffer[rb_offset].v = v1;
401                 ++rb_offset;
402
403                 render_buffer[rb_offset].x = x2;
404                 render_buffer[rb_offset].y = y2;
405                 render_buffer[rb_offset].u = u1;
406                 render_buffer[rb_offset].v = v1;
407                 ++rb_offset;
408
409                 render_buffer[rb_offset].x = x2;
410                 render_buffer[rb_offset].y = y1;
411                 render_buffer[rb_offset].u = u1;
412                 render_buffer[rb_offset].v = v0;
413                 ++rb_offset;
414
415                 render_buffer[rb_offset].x = x1;
416                 render_buffer[rb_offset].y = y1;
417                 render_buffer[rb_offset].u = u0;
418                 render_buffer[rb_offset].v = v0;
419                 ++rb_offset;
420         }
421
422         glColor4ub(gr_screen.current_color.red, gr_screen.current_color.green,
423                         gr_screen.current_color.blue,gr_screen.current_color.alpha);
424
425         glEnableClientState(GL_TEXTURE_COORD_ARRAY);
426         glEnableClientState(GL_VERTEX_ARRAY);
427
428         glTexCoordPointer(2, GL_FLOAT, sizeof(rb_t), &render_buffer[0].u);
429         glVertexPointer(2, GL_FLOAT, sizeof(rb_t), &render_buffer[0].x);
430
431         glDrawArrays(GL_QUADS, 0, rb_offset);
432
433         glDisableClientState(GL_TEXTURE_COORD_ARRAY);
434         glDisableClientState(GL_VERTEX_ARRAY);
435 }
436
437 void gr_opengl1_line(int x1,int y1,int x2,int y2)
438 {
439         int clipped = 0, swapped=0;
440
441         opengl1_set_state( TEXTURE_SOURCE_NONE, ALPHA_BLEND_ALPHA_BLEND_ALPHA, ZBUFFER_TYPE_NONE );
442
443         INT_CLIPLINE(x1,y1,x2,y2,gr_screen.clip_left,gr_screen.clip_top,gr_screen.clip_right,gr_screen.clip_bottom,return,clipped=1,swapped=1);
444
445         float sx1, sy1;
446         float sx2, sy2;
447
448         sx1 = i2fl(x1 + gr_screen.offset_x)+0.5;
449         sy1 = i2fl(y1 + gr_screen.offset_y)+0.5;
450         sx2 = i2fl(x2 + gr_screen.offset_x)+0.5;
451         sy2 = i2fl(y2 + gr_screen.offset_y)+0.5;
452
453         opengl_alloc_render_buffer(2);
454
455         if ( x1 == x2 && y1 == y2 ) {
456                 render_buffer[0].x = sx1;
457                 render_buffer[0].y = sy1;
458                 render_buffer[0].z = -0.99f;
459
460                 glColor4ub(gr_screen.current_color.red, gr_screen.current_color.green,
461                                 gr_screen.current_color.blue, gr_screen.current_color.alpha);
462
463                 glEnableClientState(GL_VERTEX_ARRAY);
464                 glVertexPointer(3, GL_FLOAT, sizeof(rb_t), &render_buffer[0].x);
465
466                 glDrawArrays(GL_POINTS, 0, 1);
467
468                 glDisableClientState(GL_VERTEX_ARRAY);
469
470                 return;
471         }
472
473         if ( x1 == x2 ) {
474                 if ( sy1 < sy2 )    {
475                         sy2 += 0.5f;
476                 } else {
477                         sy1 += 0.5f;
478                 }
479         } else if ( y1 == y2 )  {
480                 if ( sx1 < sx2 )    {
481                         sx2 += 0.5f;
482                 } else {
483                         sx1 += 0.5f;
484                 }
485         }
486
487         render_buffer[0].x = sx2;
488         render_buffer[0].y = sy2;
489         render_buffer[0].z = -0.99f;
490
491         render_buffer[1].x = sx1;
492         render_buffer[1].y = sy1;
493         render_buffer[1].z = -0.99f;
494
495         glColor4ub(gr_screen.current_color.red, gr_screen.current_color.green,
496                         gr_screen.current_color.blue, gr_screen.current_color.alpha);
497
498         glEnableClientState(GL_VERTEX_ARRAY);
499         glVertexPointer(3, GL_FLOAT, sizeof(rb_t), &render_buffer[0].x);
500
501         glDrawArrays(GL_LINES, 0, 2);
502
503         glDisableClientState(GL_VERTEX_ARRAY);
504 }
505
506 void gr_opengl1_aaline(vertex *v1, vertex *v2)
507 {
508         gr_opengl1_line( fl2i(v1->sx), fl2i(v1->sy), fl2i(v2->sx), fl2i(v2->sy) );
509 }
510
511 void gr_opengl1_gradient(int x1,int y1,int x2,int y2)
512 {
513         int clipped = 0, swapped=0;
514
515         if ( !gr_screen.current_color.is_alphacolor )   {
516                 gr_line( x1, y1, x2, y2 );
517                 return;
518         }
519
520         INT_CLIPLINE(x1,y1,x2,y2,gr_screen.clip_left,gr_screen.clip_top,gr_screen.clip_right,gr_screen.clip_bottom,return,clipped=1,swapped=1);
521
522         opengl1_set_state( TEXTURE_SOURCE_NONE, ALPHA_BLEND_ALPHA_BLEND_ALPHA, ZBUFFER_TYPE_NONE );
523
524         int aa = swapped ? 0 : gr_screen.current_color.alpha;
525         int ba = swapped ? gr_screen.current_color.alpha : 0;
526
527         float sx1, sy1;
528         float sx2, sy2;
529
530         sx1 = i2fl(x1 + gr_screen.offset_x)+0.5;
531         sy1 = i2fl(y1 + gr_screen.offset_y)+0.5;
532         sx2 = i2fl(x2 + gr_screen.offset_x)+0.5;
533         sy2 = i2fl(y2 + gr_screen.offset_y)+0.5;
534
535         if ( x1 == x2 ) {
536                 if ( sy1 < sy2 )    {
537                         sy2 += 0.5f;
538                 } else {
539                         sy1 += 0.5f;
540                 }
541         } else if ( y1 == y2 )  {
542                 if ( sx1 < sx2 )    {
543                         sx2 += 0.5f;
544                 } else {
545                         sx1 += 0.5f;
546                 }
547         }
548
549         opengl_alloc_render_buffer(2);
550
551         render_buffer[0].r = gr_screen.current_color.red;
552         render_buffer[0].g = gr_screen.current_color.green;
553         render_buffer[0].b = gr_screen.current_color.blue;
554         render_buffer[0].a = ba;
555         render_buffer[0].x = sx2;
556         render_buffer[0].y = sy2;
557         render_buffer[0].z = -0.99f;
558
559         render_buffer[1].r = gr_screen.current_color.red;
560         render_buffer[1].g = gr_screen.current_color.green;
561         render_buffer[1].b = gr_screen.current_color.blue;
562         render_buffer[1].a = aa;
563         render_buffer[1].x = sx1;
564         render_buffer[1].y = sy1;
565         render_buffer[1].z = -0.99f;
566
567         glEnableClientState(GL_COLOR_ARRAY);
568         glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(rb_t), &render_buffer[0].r);
569
570         glEnableClientState(GL_VERTEX_ARRAY);
571         glVertexPointer(3, GL_FLOAT, sizeof(rb_t), &render_buffer[0].x);
572
573         glDrawArrays(GL_LINES, 0, 2);
574
575         glDisableClientState(GL_COLOR_ARRAY);
576         glDisableClientState(GL_VERTEX_ARRAY);
577 }
578
579 void gr_opengl1_circle( int xc, int yc, int d )
580 {
581         int p,x, y, r;
582
583         r = d/2;
584         p=3-d;
585         x=0;
586         y=r;
587
588         // Big clip
589         if ( (xc+r) < gr_screen.clip_left ) return;
590         if ( (xc-r) > gr_screen.clip_right ) return;
591         if ( (yc+r) < gr_screen.clip_top ) return;
592         if ( (yc-r) > gr_screen.clip_bottom ) return;
593
594         while(x<y)      {
595                 // Draw the first octant
596                 gr_opengl1_line( xc-y, yc-x, xc+y, yc-x );
597                 gr_opengl1_line( xc-y, yc+x, xc+y, yc+x );
598
599                 if (p<0)
600                         p=p+(x<<2)+6;
601                 else    {
602                         // Draw the second octant
603                         gr_opengl1_line( xc-x, yc-y, xc+x, yc-y );
604                         gr_opengl1_line( xc-x, yc+y, xc+x, yc+y );
605
606                         p=p+((x-y)<<2)+10;
607                         y--;
608                 }
609                 x++;
610         }
611         if(x==y) {
612                 gr_opengl1_line( xc-x, yc-y, xc+x, yc-y );
613                 gr_opengl1_line( xc-x, yc+y, xc+x, yc+y );
614         }
615         return;
616 }
617
618 void gr_opengl1_pixel(int x, int y)
619 {
620         gr_line(x,y,x,y);
621 }
622
623
624 // cross fade
625 void gr_opengl1_cross_fade(int bmap1, int bmap2, int x1, int y1, int x2, int y2, float pct)
626 {
627         gr_set_bitmap(bmap1, GR_ALPHABLEND_FILTER, GR_BITBLT_MODE_NORMAL, 1.0f - pct );
628         gr_bitmap(x1, y1);
629
630         gr_set_bitmap(bmap2, GR_ALPHABLEND_FILTER, GR_BITBLT_MODE_NORMAL, pct );
631         gr_bitmap(x2, y2);
632 }
633
634 void gr_opengl1_flash(int r, int g, int b)
635 {
636         CAP(r,0,255);
637         CAP(g,0,255);
638         CAP(b,0,255);
639
640         if ( r || g || b ) {
641                 opengl1_set_state( TEXTURE_SOURCE_NONE, ALPHA_BLEND_ALPHA_ADDITIVE, ZBUFFER_TYPE_NONE );
642
643                 float x1, x2, y1, y2;
644                 x1 = i2fl(gr_screen.clip_left+gr_screen.offset_x);
645                 y1 = i2fl(gr_screen.clip_top+gr_screen.offset_y);
646                 x2 = i2fl(gr_screen.clip_right+gr_screen.offset_x);
647                 y2 = i2fl(gr_screen.clip_bottom+gr_screen.offset_y);
648
649                 glColor4ub(r, g, b, 255);
650
651                 opengl_alloc_render_buffer(4);
652
653                 render_buffer[0].x = x1;
654                 render_buffer[0].y = y2;
655                 render_buffer[0].z = -0.99f;
656
657                 render_buffer[1].x = x2;
658                 render_buffer[1].y = y2;
659                 render_buffer[1].z = -0.99f;
660
661                 render_buffer[2].x = x2;
662                 render_buffer[2].y = y1;
663                 render_buffer[2].z = -0.99f;
664
665                 render_buffer[3].x = x1;
666                 render_buffer[3].y = y1;
667                 render_buffer[3].z = -0.99f;
668
669                 glEnableClientState(GL_VERTEX_ARRAY);
670                 glVertexPointer(3, GL_FLOAT, sizeof(rb_t), &render_buffer[0].x);
671
672                 glDrawArrays(GL_QUADS, 0, 4);
673
674                 glDisableClientState(GL_VERTEX_ARRAY);
675         }
676 }
677
678 void opengl1_stuff_fog_value(float z, float *f_val)
679 {
680         float f_float;
681
682         if ( !f_val ) {
683                 return;
684         }
685
686         f_float = 1.0f - ((gr_screen.fog_far - z) / (gr_screen.fog_far - gr_screen.fog_near));
687
688         if (f_float < 0.0f) {
689                 f_float = 0.0f;
690         } else if (f_float > 1.0f) {
691                 f_float = 1.0f;
692         }
693
694         *f_val = f_float;
695 }
696
697 void opengl1_tmapper_internal( int nv, vertex ** verts, uint flags, int is_scaler )
698 {
699         int i;
700         float u_scale = 1.0f, v_scale = 1.0f;
701
702         // Make nebula use the texture mapper... this blends the colors better.
703         if ( flags & TMAP_FLAG_NEBULA ){
704                 Int3 ();
705         }
706
707         gr_texture_source texture_source = (gr_texture_source)-1;
708         gr_alpha_blend alpha_blend = (gr_alpha_blend)-1;
709         gr_zbuffer_type zbuffer_type = (gr_zbuffer_type)-1;
710
711         if ( gr_zbuffering )    {
712                 if ( is_scaler || (gr_screen.current_alphablend_mode == GR_ALPHABLEND_FILTER)   )       {
713                         zbuffer_type = ZBUFFER_TYPE_READ;
714                 } else {
715                         zbuffer_type = ZBUFFER_TYPE_FULL;
716                 }
717         } else {
718                 zbuffer_type = ZBUFFER_TYPE_NONE;
719         }
720
721         int alpha;
722
723         int tmap_type = TCACHE_TYPE_NORMAL;
724
725         int r, g, b;
726
727         if ( flags & TMAP_FLAG_TEXTURED )       {
728                 r = g = b = 255;
729         } else {
730                 r = gr_screen.current_color.red;
731                 g = gr_screen.current_color.green;
732                 b = gr_screen.current_color.blue;
733         }
734
735         if ( gr_screen.current_alphablend_mode == GR_ALPHABLEND_FILTER )
736         {
737                 if (1) {
738                         tmap_type = TCACHE_TYPE_NORMAL;
739                         alpha_blend = ALPHA_BLEND_ALPHA_ADDITIVE;
740
741                         // Blend with screen pixel using src*alpha+dst
742                         float factor = gr_screen.current_alpha;
743
744                         alpha = 255;
745
746                         if ( factor <= 1.0f )   {
747                                 int tmp_alpha = fl2i(gr_screen.current_alpha*255.0f);
748                                 r = (r*tmp_alpha)/255;
749                                 g = (g*tmp_alpha)/255;
750                                 b = (b*tmp_alpha)/255;
751                         }
752                 } else {
753                         tmap_type = TCACHE_TYPE_XPARENT;
754
755                         alpha_blend = ALPHA_BLEND_ALPHA_BLEND_ALPHA;
756
757                         // Blend with screen pixel using src*alpha+dst
758                         float factor = gr_screen.current_alpha;
759
760                         if ( factor > 1.0f )    {
761                                 alpha = 255;
762                         } else {
763                                 alpha = fl2i(gr_screen.current_alpha*255.0f);
764                         }
765                 }
766         } else {
767                 if(Bm_pixel_format == BM_PIXEL_FORMAT_ARGB) {
768                         alpha_blend = ALPHA_BLEND_ALPHA_BLEND_ALPHA;
769                 } else {
770                         alpha_blend = ALPHA_BLEND_NONE;
771                 }
772                 alpha = 255;
773         }
774
775         if (flags & TMAP_FLAG_BITMAP_SECTION) {
776                 Assert( !(flags & TMAP_FLAG_BITMAP_INTERFACE) );
777                 tmap_type = TCACHE_TYPE_BITMAP_SECTION;
778         } else if (flags & TMAP_FLAG_BITMAP_INTERFACE) {
779                 Assert( !(flags & TMAP_FLAG_BITMAP_SECTION) );
780                 tmap_type = TCACHE_TYPE_BITMAP_INTERFACE;
781         }
782
783         texture_source = TEXTURE_SOURCE_NONE;
784
785         if ( flags & TMAP_FLAG_TEXTURED )       {
786                 if ( !opengl1_tcache_set(gr_screen.current_bitmap, tmap_type, &u_scale, &v_scale, 0, gr_screen.current_bitmap_sx, gr_screen.current_bitmap_sy, 0 ))
787                 {
788                         mprintf(( "Not rendering a texture because it didn't fit in VRAM!\n" ));
789                         return;
790                 }
791
792                 // use nonfiltered textures for bitmap sections and UI graphics
793                 switch (tmap_type) {
794                         case TCACHE_TYPE_BITMAP_INTERFACE:
795                         case TCACHE_TYPE_BITMAP_SECTION:
796                                 texture_source = TEXTURE_SOURCE_NO_FILTERING;
797                                 break;
798
799                         default:
800                                 texture_source = TEXTURE_SOURCE_DECAL;
801                                 break;
802                 }
803         }
804
805
806         opengl1_set_state( texture_source, alpha_blend, zbuffer_type );
807
808         if ( flags & TMAP_FLAG_TEXTURED )
809         {
810                 // rendition junk
811                 // STUB_FUNCTION;
812         }
813
814         float fr = 1.0f, fg = 1.0f, fb = 1.0f;
815
816         if (flags & TMAP_FLAG_PIXEL_FOG) {
817                 int r, g, b;
818                 int ra, ga, ba;
819                 ra = ga = ba = 0;
820
821                 /* argh */
822                 for (i=nv-1;i>=0;i--)   // DDOI - change polygon winding
823                 {
824                         vertex * va = verts[i];
825                         float sx, sy;
826
827                         int x, y;
828                         x = fl2i(va->sx*16.0f);
829                         y = fl2i(va->sy*16.0f);
830
831                         x += gr_screen.offset_x*16;
832                         y += gr_screen.offset_y*16;
833
834                         sx = i2fl(x) / 16.0f;
835                         sy = i2fl(y) / 16.0f;
836
837                         neb2_get_pixel((int)sx, (int)sy, &r, &g, &b);
838
839                         ra += r;
840                         ga += g;
841                         ba += b;
842                 }
843
844                 ra /= nv;
845                 ga /= nv;
846                 ba /= nv;
847
848                 gr_fog_set(GR_FOGMODE_FOG, ra, ga, ba, -1.0f, -1.0f);
849
850                 fr = ra / 255.0f;
851                 fg = ga / 255.0f;
852                 fb = ba / 255.0f;
853         }
854
855         opengl_alloc_render_buffer(nv);
856
857         int rb_offset = 0;
858
859         for (i = nv-1; i >= 0; i--) {
860                 vertex * va = verts[i];
861                 float sx, sy, sz;
862                 float rhw = 1.0f;
863                 int a;
864
865                 if ( gr_zbuffering || (flags & TMAP_FLAG_NEBULA) )      {
866                         sz = 1.0 - 1.0 / (1.0 + va->z / (32768.0 / 256.0));
867
868                         if ( sz > 0.98f ) {
869                                 sz = 0.98f;
870                         }
871                 } else {
872                         sz = 0.99f;
873                 }
874
875                 if ( flags & TMAP_FLAG_CORRECT )        {
876                         rhw /= va->sw;
877                 }
878
879                 if (flags & TMAP_FLAG_ALPHA) {
880                         a = verts[i]->a;
881                 } else {
882                         a = alpha;
883                 }
884
885                 if (flags & TMAP_FLAG_NEBULA ) {
886                         int pal = (verts[i]->b*(NEBULA_COLORS-1))/255;
887                         r = gr_palette[pal*3+0];
888                         g = gr_palette[pal*3+1];
889                         b = gr_palette[pal*3+2];
890                 } else if ( (flags & TMAP_FLAG_RAMP) && (flags & TMAP_FLAG_GOURAUD) )   {
891                         r = Gr_gamma_lookup[verts[i]->b];
892                         g = Gr_gamma_lookup[verts[i]->b];
893                         b = Gr_gamma_lookup[verts[i]->b];
894                 } else if ( (flags & TMAP_FLAG_RGB)  && (flags & TMAP_FLAG_GOURAUD) )   {
895                         // Make 0.75 be 256.0f
896                         r = Gr_gamma_lookup[verts[i]->r];
897                         g = Gr_gamma_lookup[verts[i]->g];
898                         b = Gr_gamma_lookup[verts[i]->b];
899                 } else {
900                         // use constant RGB values...
901                 }
902
903                 render_buffer[rb_offset].r = r;
904                 render_buffer[rb_offset].g = g;
905                 render_buffer[rb_offset].b = b;
906                 render_buffer[rb_offset].a = a;
907
908                 if((gr_screen.current_fog_mode != GR_FOGMODE_NONE) && (OGL_fog_mode == 1)){
909                         float f_val;
910
911                         opengl1_stuff_fog_value(va->z, &f_val);
912
913                         render_buffer[rb_offset].sr = fl2i(((fr * f_val) * 255.0f) + 0.5f);
914                         render_buffer[rb_offset].sg = fl2i(((fg * f_val) * 255.0f) + 0.5f);
915                         render_buffer[rb_offset].sb = fl2i(((fb * f_val) * 255.0f) + 0.5f);
916                 }
917
918                 int x, y;
919                 x = fl2i(va->sx*16.0f);
920                 y = fl2i(va->sy*16.0f);
921
922                 x += gr_screen.offset_x*16;
923                 y += gr_screen.offset_y*16;
924
925                 sx = i2fl(x) / 16.0f;
926                 sy = i2fl(y) / 16.0f;
927
928                 if ( flags & TMAP_FLAG_TEXTURED )       {
929                         render_buffer[rb_offset].u = va->u * u_scale;
930                         render_buffer[rb_offset].v = va->v * v_scale;
931                 }
932
933                 render_buffer[rb_offset].x = sx * rhw;
934                 render_buffer[rb_offset].y = sy * rhw;
935                 render_buffer[rb_offset].z = -sz * rhw;
936                 render_buffer[rb_offset].w = rhw;
937
938                 ++rb_offset;
939         }
940
941         if (flags & TMAP_FLAG_TEXTURED) {
942                 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
943                 glTexCoordPointer(2, GL_FLOAT, sizeof(rb_t), &render_buffer[0].u);
944         }
945
946         if ( (gr_screen.current_fog_mode != GR_FOGMODE_NONE) && (OGL_fog_mode == 1) ) {
947                 glEnableClientState(GL_SECONDARY_COLOR_ARRAY);
948                 vglSecondaryColorPointerEXT(3, GL_UNSIGNED_BYTE, sizeof(rb_t), &render_buffer[0].sr);
949         }
950
951         glEnableClientState(GL_COLOR_ARRAY);
952         glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(rb_t), &render_buffer[0].r);
953
954         glEnableClientState(GL_VERTEX_ARRAY);
955         glVertexPointer(4, GL_FLOAT, sizeof(rb_t), &render_buffer[0].x);
956
957         glDrawArrays(GL_TRIANGLE_FAN, 0, rb_offset);
958
959         glDisableClientState(GL_TEXTURE_COORD_ARRAY);
960         glDisableClientState(GL_SECONDARY_COLOR_ARRAY);
961         glDisableClientState(GL_COLOR_ARRAY);
962         glDisableClientState(GL_VERTEX_ARRAY);
963 }
964
965 void gr_opengl1_tmapper( int nverts, vertex **verts, uint flags )
966 {
967         opengl1_tmapper_internal( nverts, verts, flags, 0 );
968 }
969
970 #define FIND_SCALED_NUM(x,x0,x1,y0,y1) (((((x)-(x0))*((y1)-(y0)))/((x1)-(x0)))+(y0))
971
972 void gr_opengl1_scaler(vertex *va, vertex *vb )
973 {
974         float x0, y0, x1, y1;
975         float u0, v0, u1, v1;
976         float clipped_x0, clipped_y0, clipped_x1, clipped_y1;
977         float clipped_u0, clipped_v0, clipped_u1, clipped_v1;
978         float xmin, xmax, ymin, ymax;
979         int dx0, dy0, dx1, dy1;
980
981         //============= CLIP IT =====================
982
983         x0 = va->sx; y0 = va->sy;
984         x1 = vb->sx; y1 = vb->sy;
985
986         xmin = i2fl(gr_screen.clip_left); ymin = i2fl(gr_screen.clip_top);
987         xmax = i2fl(gr_screen.clip_right); ymax = i2fl(gr_screen.clip_bottom);
988
989         u0 = va->u; v0 = va->v;
990         u1 = vb->u; v1 = vb->v;
991
992         // Check for obviously offscreen bitmaps...
993         if ( (y1<=y0) || (x1<=x0) ) return;
994         if ( (x1<xmin ) || (x0>xmax) ) return;
995         if ( (y1<ymin ) || (y0>ymax) ) return;
996
997         clipped_u0 = u0; clipped_v0 = v0;
998         clipped_u1 = u1; clipped_v1 = v1;
999
1000         clipped_x0 = x0; clipped_y0 = y0;
1001         clipped_x1 = x1; clipped_y1 = y1;
1002
1003         // Clip the left, moving u0 right as necessary
1004         if ( x0 < xmin )        {
1005                 clipped_u0 = FIND_SCALED_NUM(xmin,x0,x1,u0,u1);
1006                 clipped_x0 = xmin;
1007         }
1008
1009         // Clip the right, moving u1 left as necessary
1010         if ( x1 > xmax )        {
1011                 clipped_u1 = FIND_SCALED_NUM(xmax,x0,x1,u0,u1);
1012                 clipped_x1 = xmax;
1013         }
1014
1015         // Clip the top, moving v0 down as necessary
1016         if ( y0 < ymin )        {
1017                 clipped_v0 = FIND_SCALED_NUM(ymin,y0,y1,v0,v1);
1018                 clipped_y0 = ymin;
1019         }
1020
1021         // Clip the bottom, moving v1 up as necessary
1022         if ( y1 > ymax )        {
1023                 clipped_v1 = FIND_SCALED_NUM(ymax,y0,y1,v0,v1);
1024                 clipped_y1 = ymax;
1025         }
1026
1027         dx0 = fl2i(clipped_x0); dx1 = fl2i(clipped_x1);
1028         dy0 = fl2i(clipped_y0); dy1 = fl2i(clipped_y1);
1029
1030         if (dx1<=dx0) return;
1031         if (dy1<=dy0) return;
1032
1033         //============= DRAW IT =====================
1034
1035         vertex v[4];
1036         vertex *vl[4];
1037
1038         vl[0] = &v[0];
1039         v[0].sx = clipped_x0;
1040         v[0].sy = clipped_y0;
1041         v[0].sw = va->sw;
1042         v[0].z = va->z;
1043         v[0].u = clipped_u0;
1044         v[0].v = clipped_v0;
1045
1046         vl[1] = &v[1];
1047         v[1].sx = clipped_x1;
1048         v[1].sy = clipped_y0;
1049         v[1].sw = va->sw;
1050         v[1].z = va->z;
1051         v[1].u = clipped_u1;
1052         v[1].v = clipped_v0;
1053
1054         vl[2] = &v[2];
1055         v[2].sx = clipped_x1;
1056         v[2].sy = clipped_y1;
1057         v[2].sw = va->sw;
1058         v[2].z = va->z;
1059         v[2].u = clipped_u1;
1060         v[2].v = clipped_v1;
1061
1062         vl[3] = &v[3];
1063         v[3].sx = clipped_x0;
1064         v[3].sy = clipped_y1;
1065         v[3].sw = va->sw;
1066         v[3].z = va->z;
1067         v[3].u = clipped_u0;
1068         v[3].v = clipped_v1;
1069
1070         opengl1_tmapper_internal( 4, vl, TMAP_FLAG_TEXTURED, 1 );
1071 }