]> icculus.org git repositories - taylor/freespace2.git/blob - src/graphics/grgl2render.cpp
merge updated graphics code
[taylor/freespace2.git] / src / graphics / grgl2render.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_opengles2.h"
10
11 #include "pstypes.h"
12 #include "2d.h"
13 #include "gropengl.h"
14 #include "gropenglinternal.h"
15 #include "grgl2.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 opengl2_tmapper_internal(int nv, vertex **verts, uint flags, int is_scaler)
28 {
29         int i;
30
31         gr_texture_source texture_source = TEXTURE_SOURCE_NONE;
32         gr_alpha_blend alpha_blend = ALPHA_BLEND_ALPHA_BLEND_ALPHA;
33         gr_zbuffer_type zbuffer_type = ZBUFFER_TYPE_NONE;
34
35         if (Gr_zbuffering) {
36                 if ( is_scaler || (gr_screen.current_alphablend_mode == GR_ALPHABLEND_FILTER) ) {
37                         zbuffer_type = ZBUFFER_TYPE_READ;
38                 } else {
39                         zbuffer_type = ZBUFFER_TYPE_FULL;
40                 }
41         }
42
43         int tmap_type = TCACHE_TYPE_NORMAL;
44
45         ubyte r = 255, g = 255, b = 255, a = 255;
46
47         if ( !(flags & TMAP_FLAG_TEXTURED) ) {
48                 r = gr_screen.current_color.red;
49                 g = gr_screen.current_color.green;
50                 b = gr_screen.current_color.blue;
51         }
52
53         if (gr_screen.current_alphablend_mode == GR_ALPHABLEND_FILTER) {
54                 alpha_blend = ALPHA_BLEND_ALPHA_ADDITIVE;
55
56                 // Blend with screen pixel using src*alpha+dst
57
58                 if (gr_screen.current_alpha < 1.0f) {
59                         r = ubyte((r * gr_screen.current_alpha) + 0.5f);
60                         g = ubyte((g * gr_screen.current_alpha) + 0.5f);
61                         b = ubyte((b * gr_screen.current_alpha) + 0.5f);
62                 }
63         }
64
65         if (flags & TMAP_FLAG_BITMAP_SECTION) {
66                 SDL_assert( !(flags & TMAP_FLAG_BITMAP_INTERFACE) );
67                 tmap_type = TCACHE_TYPE_BITMAP_SECTION;
68         } else if (flags & TMAP_FLAG_BITMAP_INTERFACE) {
69                 SDL_assert( !(flags & TMAP_FLAG_BITMAP_SECTION) );
70                 tmap_type = TCACHE_TYPE_BITMAP_INTERFACE;
71         }
72
73         if (flags & TMAP_FLAG_TEXTURED) {
74                 if ( !opengl2_tcache_set(gr_screen.current_bitmap, tmap_type) ) {
75                         mprintf(( "Not rendering a texture because it didn't fit in VRAM!\n" ));
76                         return;
77                 }
78
79                 // use non-filtered textures for bitmap sections and UI graphics
80                 switch (tmap_type) {
81                         case TCACHE_TYPE_BITMAP_INTERFACE:
82                         case TCACHE_TYPE_BITMAP_SECTION:
83                                 texture_source = TEXTURE_SOURCE_NO_FILTERING;
84                                 break;
85
86                         default:
87                                 texture_source = TEXTURE_SOURCE_DECAL;
88                                 break;
89                 }
90         }
91
92
93         opengl2_set_state( texture_source, alpha_blend, zbuffer_type );
94
95         float ox = gr_screen.offset_x * 16.0f;
96         float oy = gr_screen.offset_y * 16.0f;
97
98         if (flags & TMAP_FLAG_PIXEL_FOG) {
99                 int fr, fg, fb;
100                 int ra, ga, ba;
101                 float sx, sy;
102
103                 ra = ga = ba = 0;
104
105                 for (i = nv-1; i >= 0; i--) {
106                         vertex * va = verts[i];
107
108                         sx = (va->sx * 16.0f + ox) / 16.0f;
109                         sy = (va->sy * 16.0f + oy) / 16.0f;
110
111                         neb2_get_pixel((int)sx, (int)sy, &fr, &fg, &fb);
112
113                         ra += fr;
114                         ga += fg;
115                         ba += fb;
116                 }
117
118                 ra /= nv;
119                 ga /= nv;
120                 ba /= nv;
121
122                 gr_opengl2_fog_set(GR_FOGMODE_FOG, ra, ga, ba, gr_screen.fog_near, gr_screen.fog_far);
123         }
124
125         opengl_alloc_render_buffer(nv);
126
127         int rb_offset = 0;
128
129         float sx, sy, sz = 0.99f, rhw = 1.0f;
130
131         bool bZval = (Gr_zbuffering || (flags & TMAP_FLAG_NEBULA));
132         bool bCorrect = ((flags & TMAP_FLAG_CORRECT) == TMAP_FLAG_CORRECT);
133         bool bAlpha = ((flags & TMAP_FLAG_ALPHA) == TMAP_FLAG_ALPHA);
134         bool bNebula = ((flags & TMAP_FLAG_NEBULA) == TMAP_FLAG_NEBULA);
135         bool bRamp = ((flags & TMAP_FLAG_RAMP) && (flags & TMAP_FLAG_GOURAUD));
136         bool bRGB = ((flags & TMAP_FLAG_RGB) && (flags & TMAP_FLAG_GOURAUD));
137         bool bTextured = ((flags & TMAP_FLAG_TEXTURED) == TMAP_FLAG_TEXTURED);
138         bool bFog = ((flags & TMAP_FLAG_PIXEL_FOG) == TMAP_FLAG_PIXEL_FOG);
139
140         for (i = nv-1; i >= 0; i--) {
141                 vertex *va = verts[i];
142
143                 if (bZval) {
144                         sz = 1.0f - 1.0f / (1.0f + va->z / (32768.0f / 256.0f));
145
146                         if ( sz > 0.98f ) {
147                                 sz = 0.98f;
148                         }
149                 }
150
151                 if (bCorrect) {
152                         rhw = 1.0f / va->sw;
153                 }
154
155                 if (bAlpha) {
156                         a = va->a;
157                 }
158
159                 if (bRGB) {
160                         // Make 0.75 be 256.0f
161                         r = (ubyte)Gr_gamma_lookup[va->r];
162                         g = (ubyte)Gr_gamma_lookup[va->g];
163                         b = (ubyte)Gr_gamma_lookup[va->b];
164                 } else if (bNebula) {
165                         int pal = (va->b*(NEBULA_COLORS-1))/255;
166                         r = gr_palette[pal*3+0];
167                         g = gr_palette[pal*3+1];
168                         b = gr_palette[pal*3+2];
169                 } else if (bRamp) {
170                         r = g = b = (ubyte)Gr_gamma_lookup[va->b];
171                 }
172
173                 render_buffer[rb_offset].r = r;
174                 render_buffer[rb_offset].g = g;
175                 render_buffer[rb_offset].b = b;
176                 render_buffer[rb_offset].a = a;
177
178                 if (bFog) {
179                         float f_val;
180
181                         opengl_stuff_fog_value(va->z, &f_val);
182
183                         render_buffer[rb_offset].sr = gr_screen.current_fog_color.red;
184                         render_buffer[rb_offset].sg = gr_screen.current_fog_color.green;
185                         render_buffer[rb_offset].sb = gr_screen.current_fog_color.blue;
186                         render_buffer[rb_offset].sa = (ubyte)(f_val * 255.0f);
187                 }
188
189                 sx = (va->sx * 16.0f + ox) / 16.0f;
190                 sy = (va->sy * 16.0f + oy) / 16.0f;
191
192                 if (bTextured) {
193                         render_buffer[rb_offset].u = va->u;
194                         render_buffer[rb_offset].v = va->v;
195                 }
196
197                 render_buffer[rb_offset].x = sx * rhw;
198                 render_buffer[rb_offset].y = sy * rhw;
199                 render_buffer[rb_offset].z = -sz * rhw;
200                 render_buffer[rb_offset].w = rhw;
201
202                 ++rb_offset;
203         }
204
205         sdr_prog_t program = PROG_COLOR;
206
207         if (flags & TMAP_FLAG_TEXTURED) {
208                 program = PROG_TEX;
209         }
210
211         if (flags & TMAP_FLAG_PIXEL_FOG) {
212                 // fog versions of color/tex shaders should one higher than non-fog version
213                 program = (sdr_prog_t)((int)program + 1);
214         }
215
216         opengl2_shader_use(program);
217
218         if (flags & TMAP_FLAG_TEXTURED) {
219                 glVertexAttribPointer(SDRI_TEXCOORD, 2, GL_FLOAT, GL_FALSE, sizeof(rb_t), &render_buffer[0].u);
220                 glEnableVertexAttribArray(SDRI_TEXCOORD);
221         }
222
223         if (flags & TMAP_FLAG_PIXEL_FOG) {
224                 glVertexAttribPointer(SDRI_SEC_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(rb_t), &render_buffer[0].sr);
225                 glEnableVertexAttribArray(SDRI_SEC_COLOR);
226         }
227
228         glVertexAttribPointer(SDRI_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(rb_t), &render_buffer[0].r);
229         glEnableVertexAttribArray(SDRI_COLOR);
230
231         glVertexAttribPointer(SDRI_POSITION, 4, GL_FLOAT, GL_FALSE, sizeof(rb_t), &render_buffer[0].x);
232         glEnableVertexAttribArray(SDRI_POSITION);
233
234         glDrawArrays(GL_TRIANGLE_FAN, 0, rb_offset);
235
236         glDisableVertexAttribArray(SDRI_COLOR);
237         glDisableVertexAttribArray(SDRI_SEC_COLOR);
238         glDisableVertexAttribArray(SDRI_POSITION);
239         glDisableVertexAttribArray(SDRI_TEXCOORD);
240 }
241
242 void opengl2_rect_internal(int x, int y, int w, int h, int r, int g, int b, int a)
243 {
244         int saved_zbuf = gr_zbuffer_get();
245
246         // no zbuffering, no culling
247         gr_zbuffer_set(GR_ZBUFF_NONE);
248         gr_opengl_set_cull(0);
249
250         opengl_alloc_render_buffer(4);
251
252         render_buffer[0].x = i2fl(x);
253         render_buffer[0].y = i2fl(y);
254
255         render_buffer[1].x = i2fl(x);
256         render_buffer[1].y = i2fl(y + h);
257
258         render_buffer[2].x = i2fl(x + w);
259         render_buffer[2].y = i2fl(y);
260
261         render_buffer[3].x = i2fl(x + w);
262         render_buffer[3].y = i2fl(y + h);
263
264         opengl2_shader_use(PROG_COLOR);
265
266         glVertexAttrib4f(SDRI_COLOR, r / 255.0f, g / 255.0f, b / 255.0f, a / 255.0f);
267
268         glVertexAttribPointer(SDRI_POSITION, 2, GL_FLOAT, GL_FALSE, sizeof(rb_t), &render_buffer[0].x);
269         glEnableVertexAttribArray(SDRI_POSITION);
270
271         glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
272
273         glDisableVertexAttribArray(SDRI_POSITION);
274
275         // restore zbuffer and culling
276         gr_zbuffer_set(saved_zbuf);
277         gr_opengl_set_cull(1);
278 }
279
280 void opengl2_aabitmap_ex_internal(int x, int y, int w, int h, int sx, int sy)
281 {
282         if ( (w < 1) || (h < 1) ) {
283                 return;
284         }
285
286         if ( !gr_screen.current_color.is_alphacolor ) {
287                 return;
288         }
289
290         if ( !opengl2_tcache_set(gr_screen.current_bitmap, TCACHE_TYPE_AABITMAP) ) {
291                 // Couldn't set texture
292                 mprintf(( "WARNING: Error setting aabitmap texture!\n" ));
293                 return;
294         }
295
296         opengl2_set_state( TEXTURE_SOURCE_NO_FILTERING, ALPHA_BLEND_ALPHA_BLEND_ALPHA, ZBUFFER_TYPE_NONE );
297
298         float u0, u1, v0, v1;
299         float x1, x2, y1, y2;
300         int bw, bh;
301
302         bm_get_info( gr_screen.current_bitmap, &bw, &bh );
303
304         u0 = i2fl(sx)/i2fl(bw);
305         v0 = i2fl(sy)/i2fl(bh);
306
307         u1 = i2fl(sx+w)/i2fl(bw);
308         v1 = i2fl(sy+h)/i2fl(bh);
309
310         x1 = i2fl(x+gr_screen.offset_x);
311         y1 = i2fl(y+gr_screen.offset_y);
312         x2 = i2fl(x+w+gr_screen.offset_x);
313         y2 = i2fl(y+h+gr_screen.offset_y);
314
315
316         opengl_alloc_render_buffer(4);
317
318         render_buffer[0].x = x1;
319         render_buffer[0].y = y1;
320         render_buffer[0].u = u0;
321         render_buffer[0].v = v0;
322
323         render_buffer[1].x = x1;
324         render_buffer[1].y = y2;
325         render_buffer[1].u = u0;
326         render_buffer[1].v = v1;
327
328         render_buffer[2].x = x2;
329         render_buffer[2].y = y1;
330         render_buffer[2].u = u1;
331         render_buffer[2].v = v0;
332
333         render_buffer[3].x = x2;
334         render_buffer[3].y = y2;
335         render_buffer[3].u = u1;
336         render_buffer[3].v = v1;
337
338         opengl2_shader_use(PROG_AABITMAP);
339
340         float r, g, b, a;
341         gr_get_colorf(&r, &g, &b, &a);
342         glVertexAttrib4f(SDRI_COLOR, r, g, b, a);
343
344         glVertexAttribPointer(SDRI_POSITION, 2, GL_FLOAT, GL_FALSE, sizeof(rb_t), &render_buffer[0].x);
345         glEnableVertexAttribArray(SDRI_POSITION);
346
347         glVertexAttribPointer(SDRI_TEXCOORD, 2, GL_FLOAT, GL_FALSE, sizeof(rb_t), &render_buffer[0].u);
348         glEnableVertexAttribArray(SDRI_TEXCOORD);
349
350         glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
351
352         glDisableVertexAttribArray(SDRI_POSITION);
353         glDisableVertexAttribArray(SDRI_TEXCOORD);
354 }
355
356 void gr_opengl2_rect(int x, int y, int w, int h)
357 {
358         opengl2_rect_internal(x, y, w, h, gr_screen.current_color.red,
359                         gr_screen.current_color.green, gr_screen.current_color.blue,
360                         gr_screen.current_color.alpha);
361 }
362
363 void gr_opengl2_shade(int x, int y, int w, int h)
364 {
365         int r,g,b,a;
366
367         float shade1 = 1.0f;
368         float shade2 = 6.0f;
369
370         r = fl2i(gr_screen.current_shader.r*255.0f*shade1);
371         CAP(r, 0, 255);
372         g = fl2i(gr_screen.current_shader.g*255.0f*shade1);
373         CAP(g, 0, 255);
374         b = fl2i(gr_screen.current_shader.b*255.0f*shade1);
375         CAP(b, 0, 255);
376         a = fl2i(gr_screen.current_shader.c*255.0f*shade2);
377         CAP(a, 0, 255);
378
379         opengl2_rect_internal(x, y, w, h, r, g, b, a);
380 }
381
382 void gr_opengl2_aabitmap_ex(int x, int y, int w, int h, int sx, int sy)
383 {
384         if ( (x > gr_screen.clip_right ) || ((x+w-1) < gr_screen.clip_left) )
385                 return;
386
387         if ( (y > gr_screen.clip_bottom ) || ((y+h-1) < gr_screen.clip_top) )
388                 return;
389
390         opengl2_aabitmap_ex_internal(x, y, w, h, sx, sy);
391 }
392
393 void gr_opengl2_aabitmap(int x, int y)
394 {
395         int w, h;
396
397         bm_get_info( gr_screen.current_bitmap, &w, &h, NULL );
398
399         gr_opengl2_aabitmap_ex(x, y, w, h, 0, 0);
400 }
401
402 void gr_opengl2_string(int sx, int sy, const char *s)
403 {
404         int width, spacing, letter;
405         int x, y;
406         int rb_offset;
407         float u0, u1, v0, v1;
408         float x1, x2, y1, y2;
409         int bw, bh;
410         float fbw, fbh;
411
412         if ( !Current_font )    {
413                 return;
414         }
415
416         gr_set_bitmap(Current_font->bitmap_id, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
417
418         if ( !opengl2_tcache_set( gr_screen.current_bitmap, TCACHE_TYPE_AABITMAP ) ) {
419                 // Couldn't set texture
420                 mprintf(( "WARNING: Error setting aabitmap texture!\n" ));
421                 return;
422         }
423
424         bm_get_info( gr_screen.current_bitmap, &bw, &bh );
425
426         fbw = 1.0f / i2fl(bw);
427         fbh = 1.0f / i2fl(bh);
428
429         opengl2_set_state( TEXTURE_SOURCE_NO_FILTERING, ALPHA_BLEND_ALPHA_BLEND_ALPHA, ZBUFFER_TYPE_NONE );
430
431         // don't want to create a super huge buffer size (i.e. credits text)
432         const int alocsize = 320;       // 80 characters max per render call
433         opengl_alloc_render_buffer(alocsize);
434
435         opengl2_shader_use(PROG_AABITMAP);
436
437         glVertexAttribPointer(SDRI_POSITION, 2, GL_FLOAT, GL_FALSE, sizeof(rb_t), &render_buffer[0].x);
438         glEnableVertexAttribArray(SDRI_POSITION);
439
440         float r, g, b, a;
441         gr_get_colorf(&r, &g, &b, &a);
442         glVertexAttrib4f(SDRI_COLOR, r, g, b, a);
443
444         glVertexAttribPointer(SDRI_TEXCOORD, 2, GL_FLOAT, GL_FALSE, sizeof(rb_t), &render_buffer[0].u);
445         glEnableVertexAttribArray(SDRI_TEXCOORD);
446
447
448         y = sy;
449
450         if (sx==0x8000) {                       //centered
451                 x = get_centered_x(s);
452         } else {
453                 x = sx;
454         }
455
456         spacing = 0;
457         rb_offset = 0;
458
459         while (*s)      {
460                 x += spacing;
461
462                 while (*s== '\n' )      {
463                         s++;
464                         y += Current_font->h;
465                         if (sx==0x8000) {                       //centered
466                                 x = get_centered_x(s);
467                         } else {
468                                 x = sx;
469                         }
470                 }
471                 if (*s == 0 ) break;
472
473                 letter = get_char_width(s[0],s[1],&width,&spacing);
474                 s++;
475
476                 //not in font, draw as space
477                 if (letter<0)   {
478                         continue;
479                 }
480
481                 int xd, yd, xc, yc;
482                 int wc, hc;
483
484                 // Check if this character is totally clipped
485                 if ( x + width < gr_screen.clip_left ) continue;
486                 if ( y + Current_font->h < gr_screen.clip_top ) continue;
487                 if ( x > gr_screen.clip_right ) continue;
488                 if ( y > gr_screen.clip_bottom ) continue;
489
490                 xd = yd = 0;
491                 if ( x < gr_screen.clip_left ) xd = gr_screen.clip_left - x;
492                 if ( y < gr_screen.clip_top ) yd = gr_screen.clip_top - y;
493                 xc = x+xd;
494                 yc = y+yd;
495
496                 wc = width - xd; hc = Current_font->h - yd;
497                 if ( xc + wc > gr_screen.clip_right ) wc = gr_screen.clip_right - xc;
498                 if ( yc + hc > gr_screen.clip_bottom ) hc = gr_screen.clip_bottom - yc;
499
500                 if ( wc < 1 ) continue;
501                 if ( hc < 1 ) continue;
502
503                 float u = i2fl(Current_font->bm_u[letter] + xd);
504                 float v = i2fl(Current_font->bm_v[letter] + yd);
505
506                 x1 = i2fl(xc + gr_screen.offset_x);
507                 y1 = i2fl(yc + gr_screen.offset_y);
508                 x2 = x1 + i2fl(wc);
509                 y2 = y1 + i2fl(hc);
510
511                 u0 = u * fbw;
512                 v0 = v * fbh;
513
514                 u1 = (u+i2fl(wc)) * fbw;
515                 v1 = (v+i2fl(hc)) * fbh;
516
517                 // maybe go ahead and draw
518                 if (rb_offset == alocsize) {
519                         glDrawArrays(GL_TRIANGLE_STRIP, 0, rb_offset);
520                         rb_offset = 0;
521                 }
522
523                 render_buffer[rb_offset].x = x1;
524                 render_buffer[rb_offset].y = y1;
525                 render_buffer[rb_offset].u = u0;
526                 render_buffer[rb_offset].v = v0;
527                 ++rb_offset;
528
529                 render_buffer[rb_offset].x = x1;
530                 render_buffer[rb_offset].y = y2;
531                 render_buffer[rb_offset].u = u0;
532                 render_buffer[rb_offset].v = v1;
533                 ++rb_offset;
534
535                 render_buffer[rb_offset].x = x2;
536                 render_buffer[rb_offset].y = y1;
537                 render_buffer[rb_offset].u = u1;
538                 render_buffer[rb_offset].v = v0;
539                 ++rb_offset;
540
541                 render_buffer[rb_offset].x = x2;
542                 render_buffer[rb_offset].y = y2;
543                 render_buffer[rb_offset].u = u1;
544                 render_buffer[rb_offset].v = v1;
545                 ++rb_offset;
546         }
547
548         if (rb_offset) {
549                 glDrawArrays(GL_TRIANGLE_STRIP, 0, rb_offset);
550         }
551
552         glDisableVertexAttribArray(SDRI_POSITION);
553         glDisableVertexAttribArray(SDRI_TEXCOORD);
554 }
555
556 void gr_opengl2_line(int x1, int y1, int x2, int y2)
557 {
558         opengl2_set_state(TEXTURE_SOURCE_NONE, ALPHA_BLEND_ALPHA_BLEND_ALPHA, ZBUFFER_TYPE_NONE);
559
560         INT_CLIPLINE(x1, y1, x2, y2, gr_screen.clip_left, gr_screen.clip_top,
561                 gr_screen.clip_right, gr_screen.clip_bottom, return, void(), void());
562
563         float sx1, sy1;
564         float sx2, sy2;
565
566         sx1 = i2fl(x1 + gr_screen.offset_x) + 0.5f;
567         sy1 = i2fl(y1 + gr_screen.offset_y) + 0.5f;
568         sx2 = i2fl(x2 + gr_screen.offset_x) + 0.5f;
569         sy2 = i2fl(y2 + gr_screen.offset_y) + 0.5f;
570
571         opengl_alloc_render_buffer(2);
572
573         opengl2_shader_use(PROG_COLOR);
574
575         glVertexAttribPointer(SDRI_POSITION, 2, GL_FLOAT, GL_FALSE, sizeof(rb_t), &render_buffer[0].x);
576         glEnableVertexAttribArray(SDRI_POSITION);
577
578         float r, g, b, a;
579         gr_get_colorf(&r, &g, &b, &a);
580         glVertexAttrib4f(SDRI_COLOR, r, g, b, a);
581
582         if ( (x1 == x2) && (y1 == y2) ) {
583                 render_buffer[0].x = sx1;
584                 render_buffer[0].y = sy1;
585                 render_buffer[0].z = -0.99f;
586
587                 glDrawArrays(GL_POINTS, 0, 1);
588
589                 glDisableVertexAttribArray(SDRI_POSITION);
590
591                 return;
592         }
593
594         if (x1 == x2) {
595                 if (sy1 < sy2) {
596                         sy2 += 0.5f;
597                 } else {
598                         sy1 += 0.5f;
599                 }
600         } else if (y1 == y2) {
601                 if (sx1 < sx2) {
602                         sx2 += 0.5f;
603                 } else {
604                         sx1 += 0.5f;
605                 }
606         }
607
608         render_buffer[0].x = sx2;
609         render_buffer[0].y = sy2;
610         render_buffer[0].z = -0.99f;
611
612         render_buffer[1].x = sx1;
613         render_buffer[1].y = sy1;
614         render_buffer[1].z = -0.99f;
615
616         glDrawArrays(GL_LINES, 0, 2);
617
618         glDisableVertexAttribArray(SDRI_POSITION);
619 }
620
621 void gr_opengl2_aaline(vertex *v1, vertex *v2)
622 {
623         gr_opengl2_line( fl2i(v1->sx), fl2i(v1->sy), fl2i(v2->sx), fl2i(v2->sy) );
624 }
625
626 void gr_opengl2_gradient(int x1, int y1, int x2, int y2)
627 {
628         int swapped = 0;
629
630         if ( !gr_screen.current_color.is_alphacolor ) {
631                 gr_opengl2_line(x1, y1, x2, y2);
632                 return;
633         }
634
635         INT_CLIPLINE(x1, y1, x2, y2, gr_screen.clip_left, gr_screen.clip_top,
636                         gr_screen.clip_right, gr_screen.clip_bottom, return, void(), swapped=1);
637
638         opengl2_set_state(TEXTURE_SOURCE_NONE, ALPHA_BLEND_ALPHA_BLEND_ALPHA, ZBUFFER_TYPE_NONE);
639
640         ubyte aa = swapped ? 0 : gr_screen.current_color.alpha;
641         ubyte ba = swapped ? gr_screen.current_color.alpha : 0;
642
643         float sx1, sy1;
644         float sx2, sy2;
645
646         sx1 = i2fl(x1 + gr_screen.offset_x) + 0.5f;
647         sy1 = i2fl(y1 + gr_screen.offset_y) + 0.5f;
648         sx2 = i2fl(x2 + gr_screen.offset_x) + 0.5f;
649         sy2 = i2fl(y2 + gr_screen.offset_y) + 0.5f;
650
651         if (x1 == x2) {
652                 if (sy1 < sy2) {
653                         sy2 += 0.5f;
654                 } else {
655                         sy1 += 0.5f;
656                 }
657         } else if (y1 == y2) {
658                 if (sx1 < sx2) {
659                         sx2 += 0.5f;
660                 } else {
661                         sx1 += 0.5f;
662                 }
663         }
664
665         opengl_alloc_render_buffer(2);
666
667         render_buffer[0].r = gr_screen.current_color.red;
668         render_buffer[0].g = gr_screen.current_color.green;
669         render_buffer[0].b = gr_screen.current_color.blue;
670         render_buffer[0].a = ba;
671         render_buffer[0].x = sx2;
672         render_buffer[0].y = sy2;
673         render_buffer[0].z = -0.99f;
674
675         render_buffer[1].r = gr_screen.current_color.red;
676         render_buffer[1].g = gr_screen.current_color.green;
677         render_buffer[1].b = gr_screen.current_color.blue;
678         render_buffer[1].a = aa;
679         render_buffer[1].x = sx1;
680         render_buffer[1].y = sy1;
681         render_buffer[1].z = -0.99f;
682
683         opengl2_shader_use(PROG_COLOR);
684
685         glVertexAttribPointer(SDRI_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(rb_t), &render_buffer[0].r);
686         glEnableVertexAttribArray(SDRI_COLOR);
687
688         glVertexAttribPointer(SDRI_POSITION, 3, GL_FLOAT, GL_FALSE, sizeof(rb_t), &render_buffer[0].x);
689         glEnableVertexAttribArray(SDRI_POSITION);
690
691         glDrawArrays(GL_LINES, 0, 2);
692
693         glDisableVertexAttribArray(SDRI_COLOR);
694         glDisableVertexAttribArray(SDRI_POSITION);
695 }
696
697 void gr_opengl2_circle(int xc, int yc, int d)
698 {
699         int p,x, y, r;
700
701         r = d/2;
702         p=3-d;
703         x=0;
704         y=r;
705
706         // Big clip
707         if ( (xc+r) < gr_screen.clip_left ) return;
708         if ( (xc-r) > gr_screen.clip_right ) return;
709         if ( (yc+r) < gr_screen.clip_top ) return;
710         if ( (yc-r) > gr_screen.clip_bottom ) return;
711
712         while(x<y)      {
713                 // Draw the first octant
714                 gr_opengl2_line( xc-y, yc-x, xc+y, yc-x );
715                 gr_opengl2_line( xc-y, yc+x, xc+y, yc+x );
716
717                 if (p<0)
718                         p=p+(x<<2)+6;
719                 else    {
720                         // Draw the second octant
721                         gr_opengl2_line( xc-x, yc-y, xc+x, yc-y );
722                         gr_opengl2_line( xc-x, yc+y, xc+x, yc+y );
723
724                         p=p+((x-y)<<2)+10;
725                         y--;
726                 }
727                 x++;
728         }
729         if(x==y) {
730                 gr_opengl2_line( xc-x, yc-y, xc+x, yc-y );
731                 gr_opengl2_line( xc-x, yc+y, xc+x, yc+y );
732         }
733 }
734
735 void gr_opengl2_pixel(int x, int y)
736 {
737         gr_opengl2_line(x,y,x,y);
738 }
739
740 void gr_opengl2_cross_fade(int bmap1, int bmap2, int x1, int y1, int x2, int y2, float pct)
741 {
742         gr_set_bitmap(bmap1, GR_ALPHABLEND_FILTER, GR_BITBLT_MODE_NORMAL, 1.0f - pct );
743         gr_bitmap(x1, y1);
744
745         gr_set_bitmap(bmap2, GR_ALPHABLEND_FILTER, GR_BITBLT_MODE_NORMAL, pct );
746         gr_bitmap(x2, y2);
747 }
748
749 void gr_opengl2_flash(int r, int g, int b)
750 {
751         CAP(r, 0, 255);
752         CAP(g, 0, 255);
753         CAP(b, 0, 255);
754
755         if ( r || g || b ) {
756                 opengl2_set_state(TEXTURE_SOURCE_NONE, ALPHA_BLEND_ALPHA_ADDITIVE, ZBUFFER_TYPE_NONE);
757
758                 float x1, x2, y1, y2;
759                 x1 = i2fl(gr_screen.clip_left+gr_screen.offset_x);
760                 y1 = i2fl(gr_screen.clip_top+gr_screen.offset_y);
761                 x2 = i2fl(gr_screen.clip_right+gr_screen.offset_x);
762                 y2 = i2fl(gr_screen.clip_bottom+gr_screen.offset_y);
763
764                 opengl_alloc_render_buffer(4);
765
766                 render_buffer[0].x = x1;
767                 render_buffer[0].y = y1;
768                 render_buffer[0].z = -0.99f;
769
770                 render_buffer[1].x = x1;
771                 render_buffer[1].y = y2;
772                 render_buffer[1].z = -0.99f;
773
774                 render_buffer[2].x = x2;
775                 render_buffer[2].y = y1;
776                 render_buffer[2].z = -0.99f;
777
778                 render_buffer[3].x = x2;
779                 render_buffer[3].y = y2;
780                 render_buffer[3].z = -0.99f;
781
782                 opengl2_shader_use(PROG_COLOR);
783
784                 glVertexAttrib4f(SDRI_COLOR, r / 255.0f, g / 255.0f, b / 255.0f, 1.0f);
785
786                 glVertexAttribPointer(SDRI_POSITION, 3, GL_FLOAT, GL_FALSE, sizeof(rb_t), &render_buffer[0].x);
787                 glEnableVertexAttribArray(SDRI_POSITION);
788
789                 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
790
791                 glDisableVertexAttribArray(SDRI_POSITION);
792         }
793 }
794
795 void gr_opengl2_tmapper(int nverts, vertex **verts, uint flags)
796 {
797         opengl2_tmapper_internal(nverts, verts, flags, 0);
798 }
799
800 #define FIND_SCALED_NUM(x,x0,x1,y0,y1) (((((x)-(x0))*((y1)-(y0)))/((x1)-(x0)))+(y0))
801
802 void gr_opengl2_scaler(vertex *va, vertex *vb)
803 {
804         float x0, y0, x1, y1;
805         float u0, v0, u1, v1;
806         float clipped_x0, clipped_y0, clipped_x1, clipped_y1;
807         float clipped_u0, clipped_v0, clipped_u1, clipped_v1;
808         float xmin, xmax, ymin, ymax;
809         int dx0, dy0, dx1, dy1;
810
811         //============= CLIP IT =====================
812
813         x0 = va->sx; y0 = va->sy;
814         x1 = vb->sx; y1 = vb->sy;
815
816         xmin = i2fl(gr_screen.clip_left); ymin = i2fl(gr_screen.clip_top);
817         xmax = i2fl(gr_screen.clip_right); ymax = i2fl(gr_screen.clip_bottom);
818
819         u0 = va->u; v0 = va->v;
820         u1 = vb->u; v1 = vb->v;
821
822         // Check for obviously offscreen bitmaps...
823         if ( (y1<=y0) || (x1<=x0) ) return;
824         if ( (x1<xmin ) || (x0>xmax) ) return;
825         if ( (y1<ymin ) || (y0>ymax) ) return;
826
827         clipped_u0 = u0; clipped_v0 = v0;
828         clipped_u1 = u1; clipped_v1 = v1;
829
830         clipped_x0 = x0; clipped_y0 = y0;
831         clipped_x1 = x1; clipped_y1 = y1;
832
833         // Clip the left, moving u0 right as necessary
834         if ( x0 < xmin )        {
835                 clipped_u0 = FIND_SCALED_NUM(xmin,x0,x1,u0,u1);
836                 clipped_x0 = xmin;
837         }
838
839         // Clip the right, moving u1 left as necessary
840         if ( x1 > xmax )        {
841                 clipped_u1 = FIND_SCALED_NUM(xmax,x0,x1,u0,u1);
842                 clipped_x1 = xmax;
843         }
844
845         // Clip the top, moving v0 down as necessary
846         if ( y0 < ymin )        {
847                 clipped_v0 = FIND_SCALED_NUM(ymin,y0,y1,v0,v1);
848                 clipped_y0 = ymin;
849         }
850
851         // Clip the bottom, moving v1 up as necessary
852         if ( y1 > ymax )        {
853                 clipped_v1 = FIND_SCALED_NUM(ymax,y0,y1,v0,v1);
854                 clipped_y1 = ymax;
855         }
856
857         dx0 = fl2i(clipped_x0); dx1 = fl2i(clipped_x1);
858         dy0 = fl2i(clipped_y0); dy1 = fl2i(clipped_y1);
859
860         if (dx1<=dx0) return;
861         if (dy1<=dy0) return;
862
863         //============= DRAW IT =====================
864
865         vertex v[4];
866         vertex *vl[4];
867
868         vl[0] = &v[0];
869         v[0].sx = clipped_x0;
870         v[0].sy = clipped_y0;
871         v[0].sw = va->sw;
872         v[0].z = va->z;
873         v[0].u = clipped_u0;
874         v[0].v = clipped_v0;
875
876         vl[1] = &v[1];
877         v[1].sx = clipped_x1;
878         v[1].sy = clipped_y0;
879         v[1].sw = va->sw;
880         v[1].z = va->z;
881         v[1].u = clipped_u1;
882         v[1].v = clipped_v0;
883
884         vl[2] = &v[2];
885         v[2].sx = clipped_x1;
886         v[2].sy = clipped_y1;
887         v[2].sw = va->sw;
888         v[2].z = va->z;
889         v[2].u = clipped_u1;
890         v[2].v = clipped_v1;
891
892         vl[3] = &v[3];
893         v[3].sx = clipped_x0;
894         v[3].sy = clipped_y1;
895         v[3].sw = va->sw;
896         v[3].z = va->z;
897         v[3].u = clipped_u0;
898         v[3].v = clipped_v1;
899
900         opengl2_tmapper_internal( 4, vl, TMAP_FLAG_TEXTURED, 1 );
901 }