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