2 * Copyright (C) Volition, Inc. 1999. All rights reserved.
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
9 #include "SDL_opengles2.h"
14 #include "gropenglinternal.h"
17 #include "grinternal.h"
24 #define NEBULA_COLORS 20
33 static void opengl2_tmapper_internal(int nv, vertex **verts, uint flags, int is_scaler)
36 float u_scale = 1.0f, v_scale = 1.0f;
38 gr_texture_source texture_source = TEXTURE_SOURCE_NONE;
39 gr_alpha_blend alpha_blend = ALPHA_BLEND_ALPHA_BLEND_ALPHA;
40 gr_zbuffer_type zbuffer_type = ZBUFFER_TYPE_NONE;
43 if ( is_scaler || (gr_screen.current_alphablend_mode == GR_ALPHABLEND_FILTER) ) {
44 zbuffer_type = ZBUFFER_TYPE_READ;
46 zbuffer_type = ZBUFFER_TYPE_FULL;
50 int tmap_type = TCACHE_TYPE_NORMAL;
52 ubyte r = 255, g = 255, b = 255, a = 255;
54 if ( !(flags & TMAP_FLAG_TEXTURED) ) {
55 r = gr_screen.current_color.red;
56 g = gr_screen.current_color.green;
57 b = gr_screen.current_color.blue;
60 if (gr_screen.current_alphablend_mode == GR_ALPHABLEND_FILTER) {
61 alpha_blend = ALPHA_BLEND_ALPHA_ADDITIVE;
63 // Blend with screen pixel using src*alpha+dst
65 if (gr_screen.current_alpha < 1.0f) {
66 r = ubyte((r * gr_screen.current_alpha) + 0.5f);
67 g = ubyte((g * gr_screen.current_alpha) + 0.5f);
68 b = ubyte((b * gr_screen.current_alpha) + 0.5f);
72 if (flags & TMAP_FLAG_BITMAP_SECTION) {
73 SDL_assert( !(flags & TMAP_FLAG_BITMAP_INTERFACE) );
74 tmap_type = TCACHE_TYPE_BITMAP_SECTION;
75 } else if (flags & TMAP_FLAG_BITMAP_INTERFACE) {
76 SDL_assert( !(flags & TMAP_FLAG_BITMAP_SECTION) );
77 tmap_type = TCACHE_TYPE_BITMAP_INTERFACE;
80 if (flags & TMAP_FLAG_TEXTURED) {
81 if ( !opengl2_tcache_set(gr_screen.current_bitmap, tmap_type, &u_scale,
84 mprintf(( "Not rendering a texture because it didn't fit in VRAM!\n" ));
88 // use non-filtered textures for bitmap sections and UI graphics
90 case TCACHE_TYPE_BITMAP_INTERFACE:
91 case TCACHE_TYPE_BITMAP_SECTION:
92 texture_source = TEXTURE_SOURCE_NO_FILTERING;
96 texture_source = TEXTURE_SOURCE_DECAL;
102 opengl2_set_state( texture_source, alpha_blend, zbuffer_type );
104 float ox = gr_screen.offset_x * 16.0f;
105 float oy = gr_screen.offset_y * 16.0f;
107 float fr = 1.0f, fg = 1.0f, fb = 1.0f;
109 if (flags & TMAP_FLAG_PIXEL_FOG) {
116 for (i = nv-1; i >= 0; i--) {
117 vertex * va = verts[i];
119 sx = (va->sx * 16.0f + ox) / 16.0f;
120 sy = (va->sy * 16.0f + oy) / 16.0f;
122 neb2_get_pixel((int)sx, (int)sy, &r, &g, &b);
133 gr_opengl2_fog_set(GR_FOGMODE_FOG, ra, ga, ba, gr_screen.fog_near, gr_screen.fog_far);
140 opengl_alloc_render_buffer(nv);
144 float sx, sy, sz = 0.99f, rhw = 1.0f;
146 bool bZval = (Gr_zbuffering || (flags & TMAP_FLAG_NEBULA));
147 bool bCorrect = (flags & TMAP_FLAG_CORRECT);
148 bool bAlpha = (flags & TMAP_FLAG_ALPHA);
149 bool bNebula = (flags & TMAP_FLAG_NEBULA);
150 bool bRamp = ((flags & TMAP_FLAG_RAMP) && (flags & TMAP_FLAG_GOURAUD));
151 bool bRGB = ((flags & TMAP_FLAG_RGB) && (flags & TMAP_FLAG_GOURAUD));
152 bool bTextured = (flags & TMAP_FLAG_TEXTURED);
153 bool bFog = (flags & TMAP_FLAG_PIXEL_FOG);
155 for (i = nv-1; i >= 0; i--) {
156 vertex *va = verts[i];
159 sz = 1.0f - 1.0f / (1.0f + va->z / (32768.0f / 256.0f));
175 // Make 0.75 be 256.0f
176 r = Gr_gamma_lookup[va->r];
177 g = Gr_gamma_lookup[va->g];
178 b = Gr_gamma_lookup[va->b];
179 } else if (bNebula) {
180 int pal = (va->b*(NEBULA_COLORS-1))/255;
181 r = gr_palette[pal*3+0];
182 g = gr_palette[pal*3+1];
183 b = gr_palette[pal*3+2];
185 r = g = b = Gr_gamma_lookup[va->b];
188 render_buffer[rb_offset].r = r;
189 render_buffer[rb_offset].g = g;
190 render_buffer[rb_offset].b = b;
191 render_buffer[rb_offset].a = a;
196 opengl_stuff_fog_value(va->z, &f_val);
198 render_buffer[rb_offset].sr = gr_screen.current_fog_color.red;
199 render_buffer[rb_offset].sg = gr_screen.current_fog_color.green;
200 render_buffer[rb_offset].sb = gr_screen.current_fog_color.blue;
201 render_buffer[rb_offset].sa = (ubyte)(f_val * 255.0f);
204 sx = (va->sx * 16.0f + ox) / 16.0f;
205 sy = (va->sy * 16.0f + oy) / 16.0f;
208 render_buffer[rb_offset].u = va->u * u_scale;
209 render_buffer[rb_offset].v = va->v * v_scale;
212 render_buffer[rb_offset].x = sx * rhw;
213 render_buffer[rb_offset].y = sy * rhw;
214 render_buffer[rb_offset].z = -sz * rhw;
215 render_buffer[rb_offset].w = rhw;
220 sdr_prog_t program = PROG_LINES;
222 if (flags & TMAP_FLAG_TEXTURED) {
223 program = PROG_TMAPPER;
226 opengl2_shader_use(program);
228 if (flags & TMAP_FLAG_TEXTURED) {
229 glVertexAttribPointer(SDRI_TEXCOORD, 2, GL_FLOAT, GL_FALSE, sizeof(rb_t), &render_buffer[0].u);
230 glEnableVertexAttribArray(SDRI_TEXCOORD);
233 if (flags & TMAP_FLAG_PIXEL_FOG) {
234 glVertexAttribPointer(SDRI_SEC_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(rb_t), &render_buffer[0].sr);
235 glEnableVertexAttribArray(SDRI_SEC_COLOR);
237 glVertexAttrib4f(SDRI_SEC_COLOR, 1.0f, 1.0f, 1.0f, 0.0f);
240 glVertexAttribPointer(SDRI_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(rb_t), &render_buffer[0].r);
241 glEnableVertexAttribArray(SDRI_COLOR);
243 glVertexAttribPointer(SDRI_POSITION, 4, GL_FLOAT, GL_FALSE, sizeof(rb_t), &render_buffer[0].x);
244 glEnableVertexAttribArray(SDRI_POSITION);
246 glDrawArrays(GL_TRIANGLE_FAN, 0, rb_offset);
248 glDisableVertexAttribArray(SDRI_COLOR);
249 glDisableVertexAttribArray(SDRI_SEC_COLOR);
250 glDisableVertexAttribArray(SDRI_POSITION);
251 glDisableVertexAttribArray(SDRI_TEXCOORD);
254 void opengl2_rect_internal(int x, int y, int w, int h, int r, int g, int b, int a)
258 vertex *verts[4] = {&v[0], &v[1], &v[2], &v[3]};
260 saved_zbuf = gr_zbuffer_get();
262 // start the frame, no zbuffering, no culling
264 gr_zbuffer_set(GR_ZBUFF_NONE);
265 gr_opengl_set_cull(0);
273 v[0].flags = PF_PROJECTED;
280 v[1].sx = i2fl(x + w);
285 v[1].flags = PF_PROJECTED;
292 v[2].sx = i2fl(x + w);
293 v[2].sy = i2fl(y + h);
297 v[2].flags = PF_PROJECTED;
305 v[3].sy = i2fl(y + h);
309 v[3].flags = PF_PROJECTED;
317 g3_draw_poly_constant_sw(4, verts, TMAP_FLAG_GOURAUD | TMAP_FLAG_RGB | TMAP_FLAG_ALPHA, 0.1f);
321 // restore zbuffer and culling
322 gr_zbuffer_set(saved_zbuf);
323 gr_opengl_set_cull(1);
326 void opengl2_aabitmap_ex_internal(int x, int y, int w, int h, int sx, int sy)
328 if ( (w < 1) || (h < 1) ) {
332 if ( !gr_screen.current_color.is_alphacolor ) {
336 float u_scale, v_scale;
338 if ( !opengl2_tcache_set(gr_screen.current_bitmap, TCACHE_TYPE_AABITMAP,
339 &u_scale, &v_scale, 0) )
341 // Couldn't set texture
342 mprintf(( "WARNING: Error setting aabitmap texture!\n" ));
346 opengl2_set_state( TEXTURE_SOURCE_NO_FILTERING, ALPHA_BLEND_ALPHA_BLEND_ALPHA, ZBUFFER_TYPE_NONE );
348 float u0, u1, v0, v1;
349 float x1, x2, y1, y2;
352 bm_get_info( gr_screen.current_bitmap, &bw, &bh );
354 u0 = u_scale*i2fl(sx)/i2fl(bw);
355 v0 = v_scale*i2fl(sy)/i2fl(bh);
357 u1 = u_scale*i2fl(sx+w)/i2fl(bw);
358 v1 = v_scale*i2fl(sy+h)/i2fl(bh);
360 x1 = i2fl(x+gr_screen.offset_x);
361 y1 = i2fl(y+gr_screen.offset_y);
362 x2 = i2fl(x+w+gr_screen.offset_x);
363 y2 = i2fl(y+h+gr_screen.offset_y);
366 opengl_alloc_render_buffer(4);
368 render_buffer[0].x = x1;
369 render_buffer[0].y = y1;
370 render_buffer[0].u = u0;
371 render_buffer[0].v = v0;
373 render_buffer[1].x = x1;
374 render_buffer[1].y = y2;
375 render_buffer[1].u = u0;
376 render_buffer[1].v = v1;
378 render_buffer[2].x = x2;
379 render_buffer[2].y = y1;
380 render_buffer[2].u = u1;
381 render_buffer[2].v = v0;
383 render_buffer[3].x = x2;
384 render_buffer[3].y = y2;
385 render_buffer[3].u = u1;
386 render_buffer[3].v = v1;
388 opengl2_shader_use(PROG_AABITMAP);
391 gr_get_colorf(&r, &g, &b, &a);
392 glVertexAttrib4f(SDRI_COLOR, r, g, b, a);
394 glVertexAttribPointer(SDRI_POSITION, 2, GL_FLOAT, GL_FALSE, sizeof(rb_t), &render_buffer[0].x);
395 glEnableVertexAttribArray(SDRI_POSITION);
397 glVertexAttribPointer(SDRI_TEXCOORD, 2, GL_FLOAT, GL_FALSE, sizeof(rb_t), &render_buffer[0].u);
398 glEnableVertexAttribArray(SDRI_TEXCOORD);
400 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
402 glDisableVertexAttribArray(SDRI_POSITION);
403 glDisableVertexAttribArray(SDRI_TEXCOORD);
406 void gr_opengl2_rect(int x, int y, int w, int h)
408 opengl2_rect_internal(x, y, w, h, gr_screen.current_color.red,
409 gr_screen.current_color.green, gr_screen.current_color.blue,
410 gr_screen.current_color.alpha);
413 void gr_opengl2_shade(int x, int y, int w, int h)
420 r = fl2i(gr_screen.current_shader.r*255.0f*shade1);
422 g = fl2i(gr_screen.current_shader.g*255.0f*shade1);
424 b = fl2i(gr_screen.current_shader.b*255.0f*shade1);
426 a = fl2i(gr_screen.current_shader.c*255.0f*shade2);
429 opengl2_rect_internal(x, y, w, h, r, g, b, a);
432 void gr_opengl2_aabitmap_ex(int x, int y, int w, int h, int sx, int sy)
439 int dx1=x, dx2=x+w-1;
440 int dy1=y, dy2=y+h-1;
443 bm_get_info( gr_screen.current_bitmap, &bw, &bh, NULL );
448 if ( count > 1 ) Int3();
452 if ((dx1 > gr_screen.clip_right ) || (dx2 < gr_screen.clip_left)) return;
453 if ((dy1 > gr_screen.clip_bottom ) || (dy2 < gr_screen.clip_top)) return;
454 if ( dx1 < gr_screen.clip_left ) { sx += gr_screen.clip_left-dx1; dx1 = gr_screen.clip_left; }
455 if ( dy1 < gr_screen.clip_top ) { sy += gr_screen.clip_top-dy1; dy1 = gr_screen.clip_top; }
456 if ( dx2 > gr_screen.clip_right ) { dx2 = gr_screen.clip_right; }
457 if ( dy2 > gr_screen.clip_bottom ) { dy2 = gr_screen.clip_bottom; }
484 if ( w < 1 ) return; // clipped away!
485 if ( h < 1 ) return; // clipped away!
489 // Make sure clipping algorithm works
493 SDL_assert( w == (dx2-dx1+1) );
494 SDL_assert( h == (dy2-dy1+1) );
495 SDL_assert( sx >= 0 );
496 SDL_assert( sy >= 0 );
497 SDL_assert( sx+w <= bw );
498 SDL_assert( sy+h <= bh );
499 SDL_assert( dx2 >= dx1 );
500 SDL_assert( dy2 >= dy1 );
501 SDL_assert( (dx1 >= gr_screen.clip_left ) && (dx1 <= gr_screen.clip_right) );
502 SDL_assert( (dx2 >= gr_screen.clip_left ) && (dx2 <= gr_screen.clip_right) );
503 SDL_assert( (dy1 >= gr_screen.clip_top ) && (dy1 <= gr_screen.clip_bottom) );
504 SDL_assert( (dy2 >= gr_screen.clip_top ) && (dy2 <= gr_screen.clip_bottom) );
507 // We now have dx1,dy1 and dx2,dy2 and sx, sy all set validly within clip regions.
508 opengl2_aabitmap_ex_internal(dx1,dy1,dx2-dx1+1,dy2-dy1+1,sx,sy);
511 void gr_opengl2_aabitmap(int x, int y)
515 bm_get_info( gr_screen.current_bitmap, &w, &h, NULL );
516 int dx1=x, dx2=x+w-1;
517 int dy1=y, dy2=y+h-1;
520 if ((dx1 > gr_screen.clip_right ) || (dx2 < gr_screen.clip_left)) return;
521 if ((dy1 > gr_screen.clip_bottom ) || (dy2 < gr_screen.clip_top)) return;
522 if ( dx1 < gr_screen.clip_left ) { sx = gr_screen.clip_left-dx1; dx1 = gr_screen.clip_left; }
523 if ( dy1 < gr_screen.clip_top ) { sy = gr_screen.clip_top-dy1; dy1 = gr_screen.clip_top; }
524 if ( dx2 > gr_screen.clip_right ) { dx2 = gr_screen.clip_right; }
525 if ( dy2 > gr_screen.clip_bottom ) { dy2 = gr_screen.clip_bottom; }
527 if ( sx < 0 ) return;
528 if ( sy < 0 ) return;
529 if ( sx >= w ) return;
530 if ( sy >= h ) return;
532 // Draw bitmap bm[sx,sy] into (dx1,dy1)-(dx2,dy2)
533 gr_opengl2_aabitmap_ex(dx1,dy1,dx2-dx1+1,dy2-dy1+1,sx,sy);
536 void opengl2_error_check(const char *name, int lno)
538 GLenum error = GL_NO_ERROR;
541 error = glGetError();
543 if (error != GL_NO_ERROR) {
544 nprintf(("Warning", "!!DEBUG!! OpenGL Error: %d at %s:%d\n", error, name, lno));
546 } while (error != GL_NO_ERROR);
550 void gr_opengl2_string(int sx, int sy, const char *s)
552 int width, spacing, letter;
555 float u_scale, v_scale;
556 float u0, u1, v0, v1;
557 float x1, x2, y1, y2;
561 if ( !Current_font ) {
565 gr_set_bitmap(Current_font->bitmap_id, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
567 if ( !opengl2_tcache_set( gr_screen.current_bitmap, TCACHE_TYPE_AABITMAP, &u_scale, &v_scale, 0 ) ) {
568 // Couldn't set texture
569 mprintf(( "WARNING: Error setting aabitmap texture!\n" ));
573 bm_get_info( gr_screen.current_bitmap, &bw, &bh );
575 fbw = 1.0f / i2fl(bw);
576 fbh = 1.0f / i2fl(bh);
578 opengl2_set_state( TEXTURE_SOURCE_NO_FILTERING, ALPHA_BLEND_ALPHA_BLEND_ALPHA, ZBUFFER_TYPE_NONE );
580 // don't want to create a super huge buffer size (i.e. credits text)
581 const int alocsize = 320; // 80 characters max per render call
582 opengl_alloc_render_buffer(alocsize);
584 opengl2_shader_use(PROG_AABITMAP);
586 glVertexAttribPointer(SDRI_POSITION, 2, GL_FLOAT, GL_FALSE, sizeof(rb_t), &render_buffer[0].x);
587 glEnableVertexAttribArray(SDRI_POSITION);
590 gr_get_colorf(&r, &g, &b, &a);
591 glVertexAttrib4f(SDRI_COLOR, r, g, b, a);
593 glVertexAttribPointer(SDRI_TEXCOORD, 2, GL_FLOAT, GL_FALSE, sizeof(rb_t), &render_buffer[0].u);
594 glEnableVertexAttribArray(SDRI_TEXCOORD);
599 if (sx==0x8000) { //centered
600 x = get_centered_x(s);
613 y += Current_font->h;
614 if (sx==0x8000) { //centered
615 x = get_centered_x(s);
622 letter = get_char_width(s[0],s[1],&width,&spacing);
625 //not in font, draw as space
633 // Check if this character is totally clipped
634 if ( x + width < gr_screen.clip_left ) continue;
635 if ( y + Current_font->h < gr_screen.clip_top ) continue;
636 if ( x > gr_screen.clip_right ) continue;
637 if ( y > gr_screen.clip_bottom ) continue;
640 if ( x < gr_screen.clip_left ) xd = gr_screen.clip_left - x;
641 if ( y < gr_screen.clip_top ) yd = gr_screen.clip_top - y;
645 wc = width - xd; hc = Current_font->h - yd;
646 if ( xc + wc > gr_screen.clip_right ) wc = gr_screen.clip_right - xc;
647 if ( yc + hc > gr_screen.clip_bottom ) hc = gr_screen.clip_bottom - yc;
649 if ( wc < 1 ) continue;
650 if ( hc < 1 ) continue;
652 float u = i2fl(Current_font->bm_u[letter] + xd);
653 float v = i2fl(Current_font->bm_v[letter] + yd);
655 x1 = i2fl(xc + gr_screen.offset_x);
656 y1 = i2fl(yc + gr_screen.offset_y);
660 u0 = u_scale * (u * fbw);
661 v0 = v_scale * (v * fbh);
663 u1 = u_scale * ((u+i2fl(wc)) * fbw);
664 v1 = v_scale * ((v+i2fl(hc)) * fbh);
666 // maybe go ahead and draw
667 if (rb_offset == alocsize) {
668 glDrawArrays(GL_TRIANGLE_STRIP, 0, rb_offset);
672 render_buffer[rb_offset].x = x1;
673 render_buffer[rb_offset].y = y1;
674 render_buffer[rb_offset].u = u0;
675 render_buffer[rb_offset].v = v0;
678 render_buffer[rb_offset].x = x1;
679 render_buffer[rb_offset].y = y2;
680 render_buffer[rb_offset].u = u0;
681 render_buffer[rb_offset].v = v1;
684 render_buffer[rb_offset].x = x2;
685 render_buffer[rb_offset].y = y1;
686 render_buffer[rb_offset].u = u1;
687 render_buffer[rb_offset].v = v0;
690 render_buffer[rb_offset].x = x2;
691 render_buffer[rb_offset].y = y2;
692 render_buffer[rb_offset].u = u1;
693 render_buffer[rb_offset].v = v1;
698 glDrawArrays(GL_TRIANGLE_STRIP, 0, rb_offset);
701 glDisableVertexAttribArray(SDRI_POSITION);
702 glDisableVertexAttribArray(SDRI_TEXCOORD);
705 void gr_opengl2_line(int x1, int y1, int x2, int y2)
707 opengl2_set_state(TEXTURE_SOURCE_NONE, ALPHA_BLEND_ALPHA_BLEND_ALPHA, ZBUFFER_TYPE_NONE);
709 INT_CLIPLINE(x1, y1, x2, y2, gr_screen.clip_left, gr_screen.clip_top,
710 gr_screen.clip_right, gr_screen.clip_bottom, return, void(), void());
715 sx1 = i2fl(x1 + gr_screen.offset_x) + 0.5f;
716 sy1 = i2fl(y1 + gr_screen.offset_y) + 0.5f;
717 sx2 = i2fl(x2 + gr_screen.offset_x) + 0.5f;
718 sy2 = i2fl(y2 + gr_screen.offset_y) + 0.5f;
720 opengl_alloc_render_buffer(2);
722 opengl2_shader_use(PROG_LINES);
724 glVertexAttribPointer(SDRI_POSITION, 2, GL_FLOAT, GL_FALSE, sizeof(rb_t), &render_buffer[0].x);
725 glEnableVertexAttribArray(SDRI_POSITION);
728 gr_get_colorf(&r, &g, &b, &a);
729 glVertexAttrib4f(SDRI_COLOR, r, g, b, a);
731 if ( (x1 == x2) && (y1 == y2) ) {
732 render_buffer[0].x = sx1;
733 render_buffer[0].y = sy1;
734 render_buffer[0].z = -0.99f;
736 glDrawArrays(GL_POINTS, 0, 1);
738 glDisableVertexAttribArray(SDRI_POSITION);
749 } else if (y1 == y2) {
757 render_buffer[0].x = sx2;
758 render_buffer[0].y = sy2;
759 render_buffer[0].z = -0.99f;
761 render_buffer[1].x = sx1;
762 render_buffer[1].y = sy1;
763 render_buffer[1].z = -0.99f;
765 glDrawArrays(GL_LINES, 0, 2);
767 glDisableVertexAttribArray(SDRI_POSITION);
770 void gr_opengl2_aaline(vertex *v1, vertex *v2)
772 gr_opengl2_line( fl2i(v1->sx), fl2i(v1->sy), fl2i(v2->sx), fl2i(v2->sy) );
775 void gr_opengl2_gradient(int x1, int y1, int x2, int y2)
779 if ( !gr_screen.current_color.is_alphacolor ) {
780 gr_opengl2_line(x1, y1, x2, y2);
784 INT_CLIPLINE(x1, y1, x2, y2, gr_screen.clip_left, gr_screen.clip_top,
785 gr_screen.clip_right, gr_screen.clip_bottom, return, void(), swapped=1);
787 opengl2_set_state(TEXTURE_SOURCE_NONE, ALPHA_BLEND_ALPHA_BLEND_ALPHA, ZBUFFER_TYPE_NONE);
789 ubyte aa = swapped ? 0 : gr_screen.current_color.alpha;
790 ubyte ba = swapped ? gr_screen.current_color.alpha : 0;
795 sx1 = i2fl(x1 + gr_screen.offset_x) + 0.5f;
796 sy1 = i2fl(y1 + gr_screen.offset_y) + 0.5f;
797 sx2 = i2fl(x2 + gr_screen.offset_x) + 0.5f;
798 sy2 = i2fl(y2 + gr_screen.offset_y) + 0.5f;
806 } else if (y1 == y2) {
814 opengl_alloc_render_buffer(2);
816 render_buffer[0].r = gr_screen.current_color.red;
817 render_buffer[0].g = gr_screen.current_color.green;
818 render_buffer[0].b = gr_screen.current_color.blue;
819 render_buffer[0].a = ba;
820 render_buffer[0].x = sx2;
821 render_buffer[0].y = sy2;
822 render_buffer[0].z = -0.99f;
824 render_buffer[1].r = gr_screen.current_color.red;
825 render_buffer[1].g = gr_screen.current_color.green;
826 render_buffer[1].b = gr_screen.current_color.blue;
827 render_buffer[1].a = aa;
828 render_buffer[1].x = sx1;
829 render_buffer[1].y = sy1;
830 render_buffer[1].z = -0.99f;
832 opengl2_shader_use(PROG_LINES);
834 glVertexAttribPointer(SDRI_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(rb_t), &render_buffer[0].r);
835 glEnableVertexAttribArray(SDRI_COLOR);
837 glVertexAttribPointer(SDRI_POSITION, 3, GL_FLOAT, GL_FALSE, sizeof(rb_t), &render_buffer[0].x);
838 glEnableVertexAttribArray(SDRI_POSITION);
840 glDrawArrays(GL_LINES, 0, 2);
842 glDisableVertexAttribArray(SDRI_COLOR);
843 glDisableVertexAttribArray(SDRI_POSITION);
846 void gr_opengl2_circle(int xc, int yc, int d)
856 if ( (xc+r) < gr_screen.clip_left ) return;
857 if ( (xc-r) > gr_screen.clip_right ) return;
858 if ( (yc+r) < gr_screen.clip_top ) return;
859 if ( (yc-r) > gr_screen.clip_bottom ) return;
862 // Draw the first octant
863 gr_opengl2_line( xc-y, yc-x, xc+y, yc-x );
864 gr_opengl2_line( xc-y, yc+x, xc+y, yc+x );
869 // Draw the second octant
870 gr_opengl2_line( xc-x, yc-y, xc+x, yc-y );
871 gr_opengl2_line( xc-x, yc+y, xc+x, yc+y );
879 gr_opengl2_line( xc-x, yc-y, xc+x, yc-y );
880 gr_opengl2_line( xc-x, yc+y, xc+x, yc+y );
884 void gr_opengl2_pixel(int x, int y)
886 gr_opengl2_line(x,y,x,y);
889 void gr_opengl2_cross_fade(int bmap1, int bmap2, int x1, int y1, int x2, int y2, float pct)
891 gr_set_bitmap(bmap1, GR_ALPHABLEND_FILTER, GR_BITBLT_MODE_NORMAL, 1.0f - pct );
894 gr_set_bitmap(bmap2, GR_ALPHABLEND_FILTER, GR_BITBLT_MODE_NORMAL, pct );
898 void gr_opengl2_flash(int r, int g, int b)
905 opengl2_set_state(TEXTURE_SOURCE_NONE, ALPHA_BLEND_ALPHA_ADDITIVE, ZBUFFER_TYPE_NONE);
907 float x1, x2, y1, y2;
908 x1 = i2fl(gr_screen.clip_left+gr_screen.offset_x);
909 y1 = i2fl(gr_screen.clip_top+gr_screen.offset_y);
910 x2 = i2fl(gr_screen.clip_right+gr_screen.offset_x);
911 y2 = i2fl(gr_screen.clip_bottom+gr_screen.offset_y);
913 opengl_alloc_render_buffer(4);
915 render_buffer[0].x = x1;
916 render_buffer[0].y = y1;
917 render_buffer[0].z = -0.99f;
919 render_buffer[1].x = x1;
920 render_buffer[1].y = y2;
921 render_buffer[1].z = -0.99f;
923 render_buffer[2].x = x2;
924 render_buffer[2].y = y1;
925 render_buffer[2].z = -0.99f;
927 render_buffer[3].x = x2;
928 render_buffer[3].y = y2;
929 render_buffer[3].z = -0.99f;
931 glUseProgram(PROG_LINES);
933 glVertexAttrib4f(SDRI_COLOR, r / 255.0f, g / 255.0f, b / 255.0f, 1.0f);
935 glVertexAttribPointer(SDRI_POSITION, 3, GL_FLOAT, GL_FALSE, sizeof(rb_t), &render_buffer[0].x);
936 glEnableVertexAttribArray(SDRI_POSITION);
938 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
940 glDisableVertexAttribArray(SDRI_POSITION);
944 void gr_opengl2_tmapper(int nverts, vertex **verts, uint flags)
946 opengl2_tmapper_internal(nverts, verts, flags, 0);
949 #define FIND_SCALED_NUM(x,x0,x1,y0,y1) (((((x)-(x0))*((y1)-(y0)))/((x1)-(x0)))+(y0))
951 void gr_opengl2_scaler(vertex *va, vertex *vb)
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;
960 //============= CLIP IT =====================
962 x0 = va->sx; y0 = va->sy;
963 x1 = vb->sx; y1 = vb->sy;
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);
968 u0 = va->u; v0 = va->v;
969 u1 = vb->u; v1 = vb->v;
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;
976 clipped_u0 = u0; clipped_v0 = v0;
977 clipped_u1 = u1; clipped_v1 = v1;
979 clipped_x0 = x0; clipped_y0 = y0;
980 clipped_x1 = x1; clipped_y1 = y1;
982 // Clip the left, moving u0 right as necessary
984 clipped_u0 = FIND_SCALED_NUM(xmin,x0,x1,u0,u1);
988 // Clip the right, moving u1 left as necessary
990 clipped_u1 = FIND_SCALED_NUM(xmax,x0,x1,u0,u1);
994 // Clip the top, moving v0 down as necessary
996 clipped_v0 = FIND_SCALED_NUM(ymin,y0,y1,v0,v1);
1000 // Clip the bottom, moving v1 up as necessary
1002 clipped_v1 = FIND_SCALED_NUM(ymax,y0,y1,v0,v1);
1006 dx0 = fl2i(clipped_x0); dx1 = fl2i(clipped_x1);
1007 dy0 = fl2i(clipped_y0); dy1 = fl2i(clipped_y1);
1009 if (dx1<=dx0) return;
1010 if (dy1<=dy0) return;
1012 //============= DRAW IT =====================
1018 v[0].sx = clipped_x0;
1019 v[0].sy = clipped_y0;
1022 v[0].u = clipped_u0;
1023 v[0].v = clipped_v0;
1026 v[1].sx = clipped_x1;
1027 v[1].sy = clipped_y0;
1030 v[1].u = clipped_u1;
1031 v[1].v = clipped_v0;
1034 v[2].sx = clipped_x1;
1035 v[2].sy = clipped_y1;
1038 v[2].u = clipped_u1;
1039 v[2].v = clipped_v1;
1042 v[3].sx = clipped_x0;
1043 v[3].sy = clipped_y1;
1046 v[3].u = clipped_u0;
1047 v[3].v = clipped_v1;
1049 opengl2_tmapper_internal( 4, vl, TMAP_FLAG_TEXTURED, 1 );