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