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
27 static void opengl2_tmapper_internal(int nv, vertex **verts, uint flags, int is_scaler)
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;
36 if ( is_scaler || (gr_screen.current_alphablend_mode == GR_ALPHABLEND_FILTER) ) {
37 zbuffer_type = ZBUFFER_TYPE_READ;
39 zbuffer_type = ZBUFFER_TYPE_FULL;
43 int tmap_type = TCACHE_TYPE_NORMAL;
45 ubyte r = 255, g = 255, b = 255, a = 255;
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;
53 if (gr_screen.current_alphablend_mode == GR_ALPHABLEND_FILTER) {
54 alpha_blend = ALPHA_BLEND_ALPHA_ADDITIVE;
56 // Blend with screen pixel using src*alpha+dst
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);
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;
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" ));
79 // use non-filtered textures for bitmap sections and UI graphics
81 case TCACHE_TYPE_BITMAP_INTERFACE:
82 case TCACHE_TYPE_BITMAP_SECTION:
83 texture_source = TEXTURE_SOURCE_NO_FILTERING;
87 texture_source = TEXTURE_SOURCE_DECAL;
93 opengl2_set_state( texture_source, alpha_blend, zbuffer_type );
95 float ox = gr_screen.offset_x * 16.0f;
96 float oy = gr_screen.offset_y * 16.0f;
98 if (flags & TMAP_FLAG_PIXEL_FOG) {
105 for (i = nv-1; i >= 0; i--) {
106 vertex * va = verts[i];
108 sx = (va->sx * 16.0f + ox) / 16.0f;
109 sy = (va->sy * 16.0f + oy) / 16.0f;
111 neb2_get_pixel((int)sx, (int)sy, &fr, &fg, &fb);
122 gr_opengl2_fog_set(GR_FOGMODE_FOG, ra, ga, ba, gr_screen.fog_near, gr_screen.fog_far);
125 opengl_alloc_render_buffer(nv);
129 float sx, sy, sz = 0.99f, rhw = 1.0f;
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);
140 for (i = nv-1; i >= 0; i--) {
141 vertex *va = verts[i];
144 sz = 1.0f - 1.0f / (1.0f + va->z / (32768.0f / 256.0f));
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];
170 r = g = b = (ubyte)Gr_gamma_lookup[va->b];
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;
181 opengl_stuff_fog_value(va->z, &f_val);
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);
189 sx = (va->sx * 16.0f + ox) / 16.0f;
190 sy = (va->sy * 16.0f + oy) / 16.0f;
193 render_buffer[rb_offset].u = va->u;
194 render_buffer[rb_offset].v = va->v;
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;
205 sdr_prog_t program = PROG_COLOR;
207 if (flags & TMAP_FLAG_TEXTURED) {
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);
216 opengl2_shader_use(program);
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);
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);
228 glVertexAttribPointer(SDRI_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(rb_t), &render_buffer[0].r);
229 glEnableVertexAttribArray(SDRI_COLOR);
231 glVertexAttribPointer(SDRI_POSITION, 4, GL_FLOAT, GL_FALSE, sizeof(rb_t), &render_buffer[0].x);
232 glEnableVertexAttribArray(SDRI_POSITION);
234 glDrawArrays(GL_TRIANGLE_FAN, 0, rb_offset);
236 glDisableVertexAttribArray(SDRI_COLOR);
237 glDisableVertexAttribArray(SDRI_SEC_COLOR);
238 glDisableVertexAttribArray(SDRI_POSITION);
239 glDisableVertexAttribArray(SDRI_TEXCOORD);
242 void opengl2_rect_internal(int x, int y, int w, int h, int r, int g, int b, int a)
244 int saved_zbuf = gr_zbuffer_get();
246 // no zbuffering, no culling
247 gr_zbuffer_set(GR_ZBUFF_NONE);
248 gr_opengl_set_cull(0);
250 opengl2_set_state(TEXTURE_SOURCE_NONE, ALPHA_BLEND_ALPHA_BLEND_ALPHA, ZBUFFER_TYPE_NONE);
252 opengl_alloc_render_buffer(4);
254 render_buffer[0].x = i2fl(x);
255 render_buffer[0].y = i2fl(y);
257 render_buffer[1].x = i2fl(x);
258 render_buffer[1].y = i2fl(y + h);
260 render_buffer[2].x = i2fl(x + w);
261 render_buffer[2].y = i2fl(y);
263 render_buffer[3].x = i2fl(x + w);
264 render_buffer[3].y = i2fl(y + h);
266 opengl2_shader_use(PROG_COLOR);
268 r = Gr_gamma_lookup[r];
269 g = Gr_gamma_lookup[g];
270 b = Gr_gamma_lookup[b];
272 glVertexAttrib4f(SDRI_COLOR, r / 255.0f, g / 255.0f, b / 255.0f, a / 255.0f);
274 glVertexAttribPointer(SDRI_POSITION, 2, GL_FLOAT, GL_FALSE, sizeof(rb_t), &render_buffer[0].x);
275 glEnableVertexAttribArray(SDRI_POSITION);
277 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
279 glDisableVertexAttribArray(SDRI_POSITION);
281 // restore zbuffer and culling
282 gr_zbuffer_set(saved_zbuf);
283 gr_opengl_set_cull(1);
286 void opengl2_aabitmap_ex_internal(int x, int y, int w, int h, int sx, int sy)
288 if ( (w < 1) || (h < 1) ) {
292 if ( !gr_screen.current_color.is_alphacolor ) {
296 if ( !opengl2_tcache_set(gr_screen.current_bitmap, TCACHE_TYPE_AABITMAP) ) {
297 // Couldn't set texture
298 mprintf(( "WARNING: Error setting aabitmap texture!\n" ));
302 opengl2_set_state( TEXTURE_SOURCE_NO_FILTERING, ALPHA_BLEND_ALPHA_BLEND_ALPHA, ZBUFFER_TYPE_NONE );
304 float u0, u1, v0, v1;
305 float x1, x2, y1, y2;
308 bm_get_info( gr_screen.current_bitmap, &bw, &bh );
310 u0 = i2fl(sx)/i2fl(bw);
311 v0 = i2fl(sy)/i2fl(bh);
313 u1 = i2fl(sx+w)/i2fl(bw);
314 v1 = i2fl(sy+h)/i2fl(bh);
316 x1 = i2fl(x+gr_screen.offset_x);
317 y1 = i2fl(y+gr_screen.offset_y);
318 x2 = i2fl(x+w+gr_screen.offset_x);
319 y2 = i2fl(y+h+gr_screen.offset_y);
322 opengl_alloc_render_buffer(4);
324 render_buffer[0].x = x1;
325 render_buffer[0].y = y1;
326 render_buffer[0].u = u0;
327 render_buffer[0].v = v0;
329 render_buffer[1].x = x1;
330 render_buffer[1].y = y2;
331 render_buffer[1].u = u0;
332 render_buffer[1].v = v1;
334 render_buffer[2].x = x2;
335 render_buffer[2].y = y1;
336 render_buffer[2].u = u1;
337 render_buffer[2].v = v0;
339 render_buffer[3].x = x2;
340 render_buffer[3].y = y2;
341 render_buffer[3].u = u1;
342 render_buffer[3].v = v1;
344 opengl2_shader_use(PROG_AABITMAP);
347 gr_get_colorf(&r, &g, &b, &a);
348 glVertexAttrib4f(SDRI_COLOR, r, g, b, a);
350 glVertexAttribPointer(SDRI_POSITION, 2, GL_FLOAT, GL_FALSE, sizeof(rb_t), &render_buffer[0].x);
351 glEnableVertexAttribArray(SDRI_POSITION);
353 glVertexAttribPointer(SDRI_TEXCOORD, 2, GL_FLOAT, GL_FALSE, sizeof(rb_t), &render_buffer[0].u);
354 glEnableVertexAttribArray(SDRI_TEXCOORD);
356 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
358 glDisableVertexAttribArray(SDRI_POSITION);
359 glDisableVertexAttribArray(SDRI_TEXCOORD);
362 void gr_opengl2_rect(int x, int y, int w, int h)
364 opengl2_rect_internal(x, y, w, h, gr_screen.current_color.red,
365 gr_screen.current_color.green, gr_screen.current_color.blue,
366 gr_screen.current_color.alpha);
369 void gr_opengl2_shade(int x, int y, int w, int h)
376 r = fl2i(gr_screen.current_shader.r*255.0f*shade1);
378 g = fl2i(gr_screen.current_shader.g*255.0f*shade1);
380 b = fl2i(gr_screen.current_shader.b*255.0f*shade1);
382 a = fl2i(gr_screen.current_shader.c*255.0f*shade2);
385 opengl2_rect_internal(x, y, w, h, r, g, b, a);
388 void gr_opengl2_aabitmap_ex(int x, int y, int w, int h, int sx, int sy)
390 if ( (x > gr_screen.clip_right ) || ((x+w-1) < gr_screen.clip_left) )
393 if ( (y > gr_screen.clip_bottom ) || ((y+h-1) < gr_screen.clip_top) )
396 opengl2_aabitmap_ex_internal(x, y, w, h, sx, sy);
399 void gr_opengl2_aabitmap(int x, int y)
403 bm_get_info( gr_screen.current_bitmap, &w, &h, NULL );
405 gr_opengl2_aabitmap_ex(x, y, w, h, 0, 0);
408 void gr_opengl2_string(int sx, int sy, const char *s)
410 int width, spacing, letter;
413 float u0, u1, v0, v1;
414 float x1, x2, y1, y2;
418 if ( !Current_font ) {
422 gr_set_bitmap(Current_font->bitmap_id, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
424 if ( !opengl2_tcache_set( gr_screen.current_bitmap, TCACHE_TYPE_AABITMAP ) ) {
425 // Couldn't set texture
426 mprintf(( "WARNING: Error setting aabitmap texture!\n" ));
430 bm_get_info( gr_screen.current_bitmap, &bw, &bh );
432 fbw = 1.0f / i2fl(bw);
433 fbh = 1.0f / i2fl(bh);
435 opengl2_set_state( TEXTURE_SOURCE_NO_FILTERING, ALPHA_BLEND_ALPHA_BLEND_ALPHA, ZBUFFER_TYPE_NONE );
437 // don't want to create a super huge buffer size (i.e. credits text)
438 const int alocsize = 320; // 80 characters max per render call
439 opengl_alloc_render_buffer(alocsize);
441 opengl2_shader_use(PROG_AABITMAP);
443 glVertexAttribPointer(SDRI_POSITION, 2, GL_FLOAT, GL_FALSE, sizeof(rb_t), &render_buffer[0].x);
444 glEnableVertexAttribArray(SDRI_POSITION);
447 gr_get_colorf(&r, &g, &b, &a);
448 glVertexAttrib4f(SDRI_COLOR, r, g, b, a);
450 glVertexAttribPointer(SDRI_TEXCOORD, 2, GL_FLOAT, GL_FALSE, sizeof(rb_t), &render_buffer[0].u);
451 glEnableVertexAttribArray(SDRI_TEXCOORD);
456 if (sx==0x8000) { //centered
457 x = get_centered_x(s);
470 y += Current_font->h;
471 if (sx==0x8000) { //centered
472 x = get_centered_x(s);
479 letter = get_char_width(s[0],s[1],&width,&spacing);
482 //not in font, draw as space
490 // Check if this character is totally clipped
491 if ( x + width < gr_screen.clip_left ) continue;
492 if ( y + Current_font->h < gr_screen.clip_top ) continue;
493 if ( x > gr_screen.clip_right ) continue;
494 if ( y > gr_screen.clip_bottom ) continue;
497 if ( x < gr_screen.clip_left ) xd = gr_screen.clip_left - x;
498 if ( y < gr_screen.clip_top ) yd = gr_screen.clip_top - y;
502 wc = width - xd; hc = Current_font->h - yd;
503 if ( xc + wc > gr_screen.clip_right ) wc = gr_screen.clip_right - xc;
504 if ( yc + hc > gr_screen.clip_bottom ) hc = gr_screen.clip_bottom - yc;
506 if ( wc < 1 ) continue;
507 if ( hc < 1 ) continue;
509 float u = i2fl(Current_font->bm_u[letter] + xd);
510 float v = i2fl(Current_font->bm_v[letter] + yd);
512 x1 = i2fl(xc + gr_screen.offset_x);
513 y1 = i2fl(yc + gr_screen.offset_y);
520 u1 = (u+i2fl(wc)) * fbw;
521 v1 = (v+i2fl(hc)) * fbh;
523 // maybe go ahead and draw
524 if (rb_offset == alocsize) {
525 glDrawArrays(GL_TRIANGLE_STRIP, 0, rb_offset);
529 render_buffer[rb_offset].x = x1;
530 render_buffer[rb_offset].y = y1;
531 render_buffer[rb_offset].u = u0;
532 render_buffer[rb_offset].v = v0;
535 render_buffer[rb_offset].x = x1;
536 render_buffer[rb_offset].y = y2;
537 render_buffer[rb_offset].u = u0;
538 render_buffer[rb_offset].v = v1;
541 render_buffer[rb_offset].x = x2;
542 render_buffer[rb_offset].y = y1;
543 render_buffer[rb_offset].u = u1;
544 render_buffer[rb_offset].v = v0;
547 render_buffer[rb_offset].x = x2;
548 render_buffer[rb_offset].y = y2;
549 render_buffer[rb_offset].u = u1;
550 render_buffer[rb_offset].v = v1;
555 glDrawArrays(GL_TRIANGLE_STRIP, 0, rb_offset);
558 glDisableVertexAttribArray(SDRI_POSITION);
559 glDisableVertexAttribArray(SDRI_TEXCOORD);
562 void gr_opengl2_line(int x1, int y1, int x2, int y2)
564 opengl2_set_state(TEXTURE_SOURCE_NONE, ALPHA_BLEND_ALPHA_BLEND_ALPHA, ZBUFFER_TYPE_NONE);
566 INT_CLIPLINE(x1, y1, x2, y2, gr_screen.clip_left, gr_screen.clip_top,
567 gr_screen.clip_right, gr_screen.clip_bottom, return, void(), void());
572 sx1 = i2fl(x1 + gr_screen.offset_x) + 0.5f;
573 sy1 = i2fl(y1 + gr_screen.offset_y) + 0.5f;
574 sx2 = i2fl(x2 + gr_screen.offset_x) + 0.5f;
575 sy2 = i2fl(y2 + gr_screen.offset_y) + 0.5f;
577 opengl_alloc_render_buffer(2);
579 opengl2_shader_use(PROG_COLOR);
581 glVertexAttribPointer(SDRI_POSITION, 2, GL_FLOAT, GL_FALSE, sizeof(rb_t), &render_buffer[0].x);
582 glEnableVertexAttribArray(SDRI_POSITION);
585 gr_get_colorf(&r, &g, &b, &a);
586 glVertexAttrib4f(SDRI_COLOR, r, g, b, a);
588 if ( (x1 == x2) && (y1 == y2) ) {
589 render_buffer[0].x = sx1;
590 render_buffer[0].y = sy1;
591 render_buffer[0].z = -0.99f;
593 glDrawArrays(GL_POINTS, 0, 1);
595 glDisableVertexAttribArray(SDRI_POSITION);
606 } else if (y1 == y2) {
614 render_buffer[0].x = sx2;
615 render_buffer[0].y = sy2;
616 render_buffer[0].z = -0.99f;
618 render_buffer[1].x = sx1;
619 render_buffer[1].y = sy1;
620 render_buffer[1].z = -0.99f;
622 glDrawArrays(GL_LINES, 0, 2);
624 glDisableVertexAttribArray(SDRI_POSITION);
627 void gr_opengl2_aaline(vertex *v1, vertex *v2)
629 gr_opengl2_line( fl2i(v1->sx), fl2i(v1->sy), fl2i(v2->sx), fl2i(v2->sy) );
632 void gr_opengl2_gradient(int x1, int y1, int x2, int y2)
636 if ( !gr_screen.current_color.is_alphacolor ) {
637 gr_opengl2_line(x1, y1, x2, y2);
641 INT_CLIPLINE(x1, y1, x2, y2, gr_screen.clip_left, gr_screen.clip_top,
642 gr_screen.clip_right, gr_screen.clip_bottom, return, void(), swapped=1);
644 opengl2_set_state(TEXTURE_SOURCE_NONE, ALPHA_BLEND_ALPHA_BLEND_ALPHA, ZBUFFER_TYPE_NONE);
646 ubyte aa = swapped ? 0 : gr_screen.current_color.alpha;
647 ubyte ba = swapped ? gr_screen.current_color.alpha : 0;
652 sx1 = i2fl(x1 + gr_screen.offset_x) + 0.5f;
653 sy1 = i2fl(y1 + gr_screen.offset_y) + 0.5f;
654 sx2 = i2fl(x2 + gr_screen.offset_x) + 0.5f;
655 sy2 = i2fl(y2 + gr_screen.offset_y) + 0.5f;
663 } else if (y1 == y2) {
671 opengl_alloc_render_buffer(2);
673 render_buffer[0].r = gr_screen.current_color.red;
674 render_buffer[0].g = gr_screen.current_color.green;
675 render_buffer[0].b = gr_screen.current_color.blue;
676 render_buffer[0].a = ba;
677 render_buffer[0].x = sx2;
678 render_buffer[0].y = sy2;
679 render_buffer[0].z = -0.99f;
681 render_buffer[1].r = gr_screen.current_color.red;
682 render_buffer[1].g = gr_screen.current_color.green;
683 render_buffer[1].b = gr_screen.current_color.blue;
684 render_buffer[1].a = aa;
685 render_buffer[1].x = sx1;
686 render_buffer[1].y = sy1;
687 render_buffer[1].z = -0.99f;
689 opengl2_shader_use(PROG_COLOR);
691 glVertexAttribPointer(SDRI_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(rb_t), &render_buffer[0].r);
692 glEnableVertexAttribArray(SDRI_COLOR);
694 glVertexAttribPointer(SDRI_POSITION, 3, GL_FLOAT, GL_FALSE, sizeof(rb_t), &render_buffer[0].x);
695 glEnableVertexAttribArray(SDRI_POSITION);
697 glDrawArrays(GL_LINES, 0, 2);
699 glDisableVertexAttribArray(SDRI_COLOR);
700 glDisableVertexAttribArray(SDRI_POSITION);
703 void gr_opengl2_circle(int xc, int yc, int d)
713 if ( (xc+r) < gr_screen.clip_left ) return;
714 if ( (xc-r) > gr_screen.clip_right ) return;
715 if ( (yc+r) < gr_screen.clip_top ) return;
716 if ( (yc-r) > gr_screen.clip_bottom ) return;
719 // Draw the first octant
720 gr_opengl2_line( xc-y, yc-x, xc+y, yc-x );
721 gr_opengl2_line( xc-y, yc+x, xc+y, yc+x );
726 // Draw the second octant
727 gr_opengl2_line( xc-x, yc-y, xc+x, yc-y );
728 gr_opengl2_line( xc-x, yc+y, xc+x, yc+y );
736 gr_opengl2_line( xc-x, yc-y, xc+x, yc-y );
737 gr_opengl2_line( xc-x, yc+y, xc+x, yc+y );
741 void gr_opengl2_pixel(int x, int y)
743 gr_opengl2_line(x,y,x,y);
746 void gr_opengl2_cross_fade(int bmap1, int bmap2, int x1, int y1, int x2, int y2, float pct)
748 gr_set_bitmap(bmap1, GR_ALPHABLEND_FILTER, GR_BITBLT_MODE_NORMAL, 1.0f - pct );
751 gr_set_bitmap(bmap2, GR_ALPHABLEND_FILTER, GR_BITBLT_MODE_NORMAL, pct );
755 void gr_opengl2_flash(int r, int g, int b)
762 opengl2_set_state(TEXTURE_SOURCE_NONE, ALPHA_BLEND_ALPHA_ADDITIVE, ZBUFFER_TYPE_NONE);
764 float x1, x2, y1, y2;
765 x1 = i2fl(gr_screen.clip_left+gr_screen.offset_x);
766 y1 = i2fl(gr_screen.clip_top+gr_screen.offset_y);
767 x2 = i2fl(gr_screen.clip_right+gr_screen.offset_x);
768 y2 = i2fl(gr_screen.clip_bottom+gr_screen.offset_y);
770 opengl_alloc_render_buffer(4);
772 render_buffer[0].x = x1;
773 render_buffer[0].y = y1;
774 render_buffer[0].z = -0.99f;
776 render_buffer[1].x = x1;
777 render_buffer[1].y = y2;
778 render_buffer[1].z = -0.99f;
780 render_buffer[2].x = x2;
781 render_buffer[2].y = y1;
782 render_buffer[2].z = -0.99f;
784 render_buffer[3].x = x2;
785 render_buffer[3].y = y2;
786 render_buffer[3].z = -0.99f;
788 opengl2_shader_use(PROG_COLOR);
790 glVertexAttrib4f(SDRI_COLOR, r / 255.0f, g / 255.0f, b / 255.0f, 1.0f);
792 glVertexAttribPointer(SDRI_POSITION, 3, GL_FLOAT, GL_FALSE, sizeof(rb_t), &render_buffer[0].x);
793 glEnableVertexAttribArray(SDRI_POSITION);
795 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
797 glDisableVertexAttribArray(SDRI_POSITION);
801 void gr_opengl2_tmapper(int nverts, vertex **verts, uint flags)
803 opengl2_tmapper_internal(nverts, verts, flags, 0);
806 #define FIND_SCALED_NUM(x,x0,x1,y0,y1) (((((x)-(x0))*((y1)-(y0)))/((x1)-(x0)))+(y0))
808 void gr_opengl2_scaler(vertex *va, vertex *vb)
810 float x0, y0, x1, y1;
811 float u0, v0, u1, v1;
812 float clipped_x0, clipped_y0, clipped_x1, clipped_y1;
813 float clipped_u0, clipped_v0, clipped_u1, clipped_v1;
814 float xmin, xmax, ymin, ymax;
815 int dx0, dy0, dx1, dy1;
817 //============= CLIP IT =====================
819 x0 = va->sx; y0 = va->sy;
820 x1 = vb->sx; y1 = vb->sy;
822 xmin = i2fl(gr_screen.clip_left); ymin = i2fl(gr_screen.clip_top);
823 xmax = i2fl(gr_screen.clip_right); ymax = i2fl(gr_screen.clip_bottom);
825 u0 = va->u; v0 = va->v;
826 u1 = vb->u; v1 = vb->v;
828 // Check for obviously offscreen bitmaps...
829 if ( (y1<=y0) || (x1<=x0) ) return;
830 if ( (x1<xmin ) || (x0>xmax) ) return;
831 if ( (y1<ymin ) || (y0>ymax) ) return;
833 clipped_u0 = u0; clipped_v0 = v0;
834 clipped_u1 = u1; clipped_v1 = v1;
836 clipped_x0 = x0; clipped_y0 = y0;
837 clipped_x1 = x1; clipped_y1 = y1;
839 // Clip the left, moving u0 right as necessary
841 clipped_u0 = FIND_SCALED_NUM(xmin,x0,x1,u0,u1);
845 // Clip the right, moving u1 left as necessary
847 clipped_u1 = FIND_SCALED_NUM(xmax,x0,x1,u0,u1);
851 // Clip the top, moving v0 down as necessary
853 clipped_v0 = FIND_SCALED_NUM(ymin,y0,y1,v0,v1);
857 // Clip the bottom, moving v1 up as necessary
859 clipped_v1 = FIND_SCALED_NUM(ymax,y0,y1,v0,v1);
863 dx0 = fl2i(clipped_x0); dx1 = fl2i(clipped_x1);
864 dy0 = fl2i(clipped_y0); dy1 = fl2i(clipped_y1);
866 if (dx1<=dx0) return;
867 if (dy1<=dy0) return;
869 //============= DRAW IT =====================
875 v[0].sx = clipped_x0;
876 v[0].sy = clipped_y0;
883 v[1].sx = clipped_x1;
884 v[1].sy = clipped_y0;
891 v[2].sx = clipped_x1;
892 v[2].sy = clipped_y1;
899 v[3].sx = clipped_x0;
900 v[3].sy = clipped_y1;
906 opengl2_tmapper_internal( 4, vl, TMAP_FLAG_TEXTURED, 1 );