1 /* $Id: ogl.c,v 1.39 2006-11-30 13:42:20 chris Exp $ */
4 * Graphics support functions for OpenGL.
19 #if defined(__APPLE__) && defined(__MACH__)
20 #include <OpenGL/gl.h>
21 #include <OpenGL/glu.h>
32 #include "../../3d/globvars.h"
54 //change to 1 for lots of spew.
56 #define glmprintf(a) mprintf(a)
65 #if defined(_WIN32) || (defined(__APPLE__) && defined(__MACH__)) || defined(__sun__) || defined(macintosh)
66 #define cosf(a) cos(a)
67 #define sinf(a) sin(a)
70 unsigned char *ogl_pal=gr_palette;
72 int GL_texmagfilt=GL_NEAREST;
73 int GL_texminfilt=GL_NEAREST;
74 float GL_texanisofilt = 0;
77 int last_width=-1,last_height=-1;
78 int GL_TEXTURE_2D_enabled=-1;
79 int GL_texclamp_enabled=-1;
81 extern int gr_badtexture;
82 int r_texcount = 0, r_cachedtexcount = 0;
83 int ogl_alttexmerge=1;//merge textures by just printing the seperate textures?
84 int ogl_rgba_internalformat = GL_RGBA8;
85 int ogl_rgb_internalformat = GL_RGB8;
86 int ogl_intensity4_ok=1;
87 int ogl_luminance4_alpha4_ok=1;
89 int ogl_readpixels_ok=1;
90 int ogl_gettexlevelparam_ok=1;
91 #ifdef GL_ARB_multitexture
92 int ogl_arb_multitexture_ok=0;
94 #ifdef GL_SGIS_multitexture
95 int ogl_sgis_multitexture_ok=0;
97 int ogl_nv_texture_env_combine4_ok = 0;
98 #ifdef GL_NV_register_combiners
99 int ogl_nv_register_combiners_ok = 0;
101 int ogl_ext_texture_filter_anisotropic_ok = 0;
102 #ifdef GL_EXT_paletted_texture
103 int ogl_shared_palette_ok = 0;
104 int ogl_paletted_texture_ok = 0;
108 int cross_lh[2]={0,0};
109 int primary_lh[3]={0,0,0};
110 int secondary_lh[5]={0,0,0,0,0};
113 #define OGL_BINDTEXTURE(a) if(gr_badtexture>0) glBindTexture(GL_TEXTURE_2D, 0);\
114 else if(a!=lastbound) {glBindTexture(GL_TEXTURE_2D, a);lastbound=a;}*/
115 #define OGL_BINDTEXTURE(a) if(gr_badtexture>0) glBindTexture(GL_TEXTURE_2D, 0);\
116 else glBindTexture(GL_TEXTURE_2D, a);
119 ogl_texture ogl_texture_list[OGL_TEXTURE_LIST_SIZE];
120 int ogl_texture_list_cur;
122 /* some function prototypes */
124 //#define OGLTEXBUFSIZE (1024*1024*4)
125 #define OGLTEXBUFSIZE (2048*2048*4)
126 extern GLubyte texbuf[OGLTEXBUFSIZE];
127 //void ogl_filltexbuf(unsigned char *data,GLubyte *texp,int width,int height,int twidth,int theight);
128 void ogl_filltexbuf(unsigned char *data, GLubyte *texp, int truewidth, int width, int height, int dxo, int dyo, int twidth, int theight, int type, int bm_flags, int data_format);
129 void ogl_loadbmtexture(grs_bitmap *bm);
130 //void ogl_loadtexture(unsigned char * data, int width, int height,int dxo,intdyo , int *texid,float *u,float *v,char domipmap,float prio);
131 void ogl_loadtexture(unsigned char *data, int dxo, int dyo, ogl_texture *tex, int bm_flags, int data_format);
132 void ogl_freetexture(ogl_texture *gltexture);
133 void ogl_do_palfx(void);
135 void ogl_init_texture_stats(ogl_texture* t){
136 t->prio=0.3;//default prio
140 void ogl_init_texture(ogl_texture* t, int w, int h, int flags)
143 if (flags & OGL_FLAG_NOCOLOR)
145 // use GL_INTENSITY instead of GL_RGB
146 if (flags & OGL_FLAG_ALPHA)
148 if (ogl_intensity4_ok)
150 t->internalformat = GL_INTENSITY4;
151 t->format = GL_LUMINANCE;
153 else if (ogl_luminance4_alpha4_ok)
155 t->internalformat = GL_LUMINANCE4_ALPHA4;
156 t->format = GL_LUMINANCE_ALPHA;
158 else if (ogl_rgba2_ok)
160 t->internalformat = GL_RGBA2;
165 t->internalformat = ogl_rgba_internalformat;
171 // there are certainly smaller formats we could use here, but nothing needs it ATM.
172 t->internalformat = ogl_rgb_internalformat;
178 if (flags & OGL_FLAG_ALPHA)
180 t->internalformat = ogl_rgba_internalformat;
185 t->internalformat = ogl_rgb_internalformat;
189 t->wrapstate[0] = -1;
190 t->wrapstate[1] = -1;
193 t->wantmip = flags & OGL_FLAG_MIPMAP;
194 ogl_init_texture_stats(t);
197 void ogl_reset_texture(ogl_texture* t)
199 ogl_init_texture(t, 0, 0, 0);
202 void ogl_reset_texture_stats_internal(void){
204 for (i=0;i<OGL_TEXTURE_LIST_SIZE;i++)
205 if (ogl_texture_list[i].handle>0){
206 ogl_init_texture_stats(&ogl_texture_list[i]);
209 void ogl_init_texture_list_internal(void){
211 ogl_texture_list_cur=0;
212 for (i=0;i<OGL_TEXTURE_LIST_SIZE;i++)
213 ogl_reset_texture(&ogl_texture_list[i]);
215 void ogl_smash_texture_list_internal(void){
218 memset(cross_lh,0,sizeof(cross_lh));
219 memset(primary_lh,0,sizeof(primary_lh));
220 memset(secondary_lh,0,sizeof(secondary_lh));
221 for (i=0;i<OGL_TEXTURE_LIST_SIZE;i++){
222 if (ogl_texture_list[i].handle>0){
223 glDeleteTextures( 1, &ogl_texture_list[i].handle );
224 ogl_texture_list[i].handle=0;
226 ogl_texture_list[i].wrapstate[0] = -1;
227 ogl_texture_list[i].wrapstate[1] = -1;
230 void ogl_vivify_texture_list_internal(void){
234 for (i=0;i<OGL_TEXTURE_LIST_SIZE;i++){
235 t=&ogl_texture_list[i];
236 if (t->w>0){//erk, realised this can't be done since we'd need the texture bm_data too. hmmm.
237 ogl_loadbmtexture(t);
242 ogl_texture* ogl_get_free_texture(void){
244 for (i=0;i<OGL_TEXTURE_LIST_SIZE;i++){
245 if (ogl_texture_list[ogl_texture_list_cur].handle<=0 && ogl_texture_list[ogl_texture_list_cur].w==0)
246 return &ogl_texture_list[ogl_texture_list_cur];
247 if (++ogl_texture_list_cur>=OGL_TEXTURE_LIST_SIZE)
248 ogl_texture_list_cur=0;
250 Error("OGL: texture list full!\n");
253 int ogl_texture_stats(void){
254 int used = 0, usedother = 0, usedidx = 0, usedrgb = 0, usedrgba = 0;
255 int databytes = 0, truebytes = 0, datatexel = 0, truetexel = 0, i;
256 int prio0=0,prio1=0,prio2=0,prio3=0,prioh=0;
259 for (i=0;i<OGL_TEXTURE_LIST_SIZE;i++){
260 t=&ogl_texture_list[i];
263 datatexel+=t->w*t->h;
264 truetexel+=t->tw*t->th;
265 databytes+=t->bytesu;
267 if (t->prio<0.299)prio0++;
268 else if (t->prio<0.399)prio1++;
269 else if (t->prio<0.499)prio2++;
270 else if (t->prio<0.599)prio3++;
272 if (t->format == GL_RGBA)
274 else if (t->format == GL_RGB)
276 else if (t->format == GL_COLOR_INDEX)
286 GLint idx, r, g, b, a, dbl, depth;
287 int res, colorsize, depthsize;
289 res = SWIDTH * SHEIGHT;
290 glGetIntegerv(GL_INDEX_BITS, &idx);
291 glGetIntegerv(GL_RED_BITS, &r);
292 glGetIntegerv(GL_GREEN_BITS, &g);
293 glGetIntegerv(GL_BLUE_BITS, &b);
294 glGetIntegerv(GL_ALPHA_BITS, &a);
295 glGetIntegerv(GL_DOUBLEBUFFER, &dbl);
297 glGetIntegerv(GL_DEPTH_BITS, &depth);
298 colorsize = (idx * res * dbl) / 8;
299 depthsize = res * depth / 8;
300 gr_printf(5, GAME_FONT->ft_h * 14 + 3 * 14, "%i(%i,%i,%i,%i) %iK(%iK wasted) (%i postcachedtex)", used, usedrgba, usedrgb, usedidx, usedother, truebytes / 1024, (truebytes - databytes) / 1024, r_texcount - r_cachedtexcount);
301 gr_printf(5, GAME_FONT->ft_h * 15 + 3 * 15, "%ibpp(r%i,g%i,b%i,a%i)x%i=%iK depth%i=%iK", idx, r, g, b, a, dbl, colorsize / 1024, depth, depthsize / 1024);
302 gr_printf(5, GAME_FONT->ft_h * 16 + 3 * 16, "total=%iK", (colorsize + depthsize + truebytes) / 1024);
304 // glmprintf((0,"ogl tex stats: %i(%i,%i|%i,%i,%i,%i,%i) %i(%i)b (%i(%i)wasted)\n",used,usedrgba,usedl4a4,prio0,prio1,prio2,prio3,prioh,truebytes,truetexel,truebytes-databytes,truetexel-datatexel));
307 int ogl_mem_target=-1;
308 void ogl_clean_texture_cache(void){
313 if (ogl_mem_target<0){
319 bytes=ogl_texture_stats();
320 while (bytes>ogl_mem_target){
321 for (i=0;i<OGL_TEXTURE_LIST_SIZE;i++){
322 t=&ogl_texture_list[i];
324 if (t->lastrend+f1_0*time<GameTime){
327 if (bytes<ogl_mem_target)
333 Error("not enough mem?");
338 void ogl_bindbmtex(grs_bitmap *bm){
339 if (bm->gltexture==NULL || bm->gltexture->handle<=0)
340 ogl_loadbmtexture(bm);
341 OGL_BINDTEXTURE(bm->gltexture->handle);
342 bm->gltexture->lastrend=GameTime;
343 bm->gltexture->numrend++;
344 //// if (bm->gltexture->numrend==80 || bm->gltexture->numrend==4000 || bm->gltexture->numrend==80000){
345 // if (bm->gltexture->numrend==100){
346 // bm->gltexture->prio+=0.1;
347 //// glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_PRIORITY,bm->gltexture->prio);
348 // glPrioritizeTextures(1,&bm->gltexture->handle,&bm->gltexture->prio);
351 //gltexture MUST be bound first
352 void ogl_texwrap(ogl_texture *gltexture,int state)
354 if (gltexture->wrapstate[active_texture_unit] != state || gltexture->numrend < 1)
356 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, state);
357 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, state);
358 gltexture->wrapstate[active_texture_unit] = state;
362 //crude texture precaching
363 //handles: powerups, walls, weapons, polymodels, etc.
364 //it is done with the horrid do_special_effects kludge so that sides that have to be texmerged and have animated textures will be correctly cached.
365 //similarly, with the objects(esp weapons), we could just go through and cache em all instead, but that would get ones that might not even be on the level
368 void ogl_cache_polymodel_textures(int model_num)
375 po = &Polygon_models[model_num];
376 for (i=0;i<po->n_textures;i++) {
377 // texture_list_index[i] = ObjBitmaps[ObjBitmapPtrs[po->first_texture+i]];
378 ogl_loadbmtexture(&GameBitmaps[ObjBitmaps[ObjBitmapPtrs[po->first_texture+i]].index]);
381 void ogl_cache_vclip_textures(vclip *vc){
383 for (i=0;i<vc->num_frames;i++){
384 PIGGY_PAGE_IN(vc->frames[i]);
385 ogl_loadbmtexture(&GameBitmaps[vc->frames[i].index]);
389 void ogl_cache_vclipn_textures(int i)
391 if (i >= 0 && i < VCLIP_MAXNUM)
392 ogl_cache_vclip_textures(&Vclip[i]);
395 void ogl_cache_weapon_textures(int weapon_type)
401 w = &Weapon_info[weapon_type];
402 ogl_cache_vclipn_textures(w->flash_vclip);
403 ogl_cache_vclipn_textures(w->robot_hit_vclip);
404 ogl_cache_vclipn_textures(w->wall_hit_vclip);
405 if (w->render_type==WEAPON_RENDER_VCLIP)
406 ogl_cache_vclipn_textures(w->weapon_vclip);
407 else if (w->render_type == WEAPON_RENDER_POLYMODEL)
409 ogl_cache_polymodel_textures(w->model_num);
410 ogl_cache_polymodel_textures(w->model_num_inner);
414 void ogl_cache_level_textures(void)
423 ogl_reset_texture_stats_internal();//loading a new lev should reset textures
425 for (i=0,ec=Effects;i<Num_effects;i++,ec++) {
426 ogl_cache_vclipn_textures(Effects[i].dest_vclip);
427 if ((Effects[i].changing_wall_texture == -1) && (Effects[i].changing_object_texture==-1) )
429 if (ec->vc.num_frames>max_efx)
430 max_efx=ec->vc.num_frames;
432 glmprintf((0,"max_efx:%i\n",max_efx));
433 for (ef=0;ef<max_efx;ef++){
434 for (i=0,ec=Effects;i<Num_effects;i++,ec++) {
435 if ((Effects[i].changing_wall_texture == -1) && (Effects[i].changing_object_texture==-1) )
437 // if (ec->vc.num_frames>max_efx)
438 // max_efx=ec->vc.num_frames;
441 do_special_effects();
443 for (seg=0;seg<Num_segments;seg++){
444 for (side=0;side<MAX_SIDES_PER_SEGMENT;side++){
445 sidep=&Segments[seg].sides[side];
446 tmap1=sidep->tmap_num;
447 tmap2=sidep->tmap_num2;
448 if (tmap1<0 || tmap1>=NumTextures){
449 glmprintf((0,"ogl_cache_level_textures %i %i %i %i\n",seg,side,tmap1,NumTextures));
453 PIGGY_PAGE_IN(Textures[tmap1]);
454 bm = &GameBitmaps[Textures[tmap1].index];
456 PIGGY_PAGE_IN(Textures[tmap2&0x3FFF]);
457 bm2 = &GameBitmaps[Textures[tmap2&0x3FFF].index];
458 if (ogl_alttexmerge == 0 || (!OGL_SUPER_TRANSPARENT_OK && (bm2->bm_flags & BM_FLAG_SUPER_TRANSPARENT)))
459 bm = texmerge_get_cached_bitmap( tmap1, tmap2 );
461 ogl_loadbmtexture(bm2);
463 // glmprintf((0,"ogl_cache_level_textures seg %i side %i t1 %i t2 %x bm %p NT %i\n",seg,side,tmap1,tmap2,bm,NumTextures));
465 ogl_loadbmtexture(bm);
468 glmprintf((0,"finished ef:%i\n",ef));
470 reset_special_effects();
471 init_special_effects();
475 // always have lasers, concs, flares. Always shows player appearance, and at least concs are always available to disappear.
476 ogl_cache_weapon_textures(Primary_weapon_to_weapon_info[LASER_INDEX]);
477 ogl_cache_weapon_textures(Secondary_weapon_to_weapon_info[CONCUSSION_INDEX]);
478 ogl_cache_weapon_textures(FLARE_ID);
479 ogl_cache_vclipn_textures(VCLIP_PLAYER_APPEARANCE);
480 ogl_cache_vclipn_textures(VCLIP_POWERUP_DISAPPEARANCE);
481 ogl_cache_polymodel_textures(Player_ship->model_num);
482 ogl_cache_vclipn_textures(Player_ship->expl_vclip_num);
484 for (i=0;i<Highest_object_index;i++){
485 if(Objects[i].render_type==RT_POWERUP){
486 ogl_cache_vclipn_textures(Objects[i].rtype.vclip_info.vclip_num);
487 switch (Objects[i].id){
489 ogl_cache_weapon_textures(Primary_weapon_to_weapon_info[LASER_INDEX]);
493 case POW_VULCAN_WEAPON:
494 ogl_cache_weapon_textures(Primary_weapon_to_weapon_info[VULCAN_INDEX]);
496 case POW_SPREADFIRE_WEAPON:
497 ogl_cache_weapon_textures(Primary_weapon_to_weapon_info[SPREADFIRE_INDEX]);
499 case POW_PLASMA_WEAPON:
500 ogl_cache_weapon_textures(Primary_weapon_to_weapon_info[PLASMA_INDEX]);
502 case POW_FUSION_WEAPON:
503 ogl_cache_weapon_textures(Primary_weapon_to_weapon_info[FUSION_INDEX]);
505 /* case POW_MISSILE_1:
507 ogl_cache_weapon_textures(Secondary_weapon_to_weapon_info[CONCUSSION_INDEX]);
509 case POW_PROXIMITY_WEAPON:
510 ogl_cache_weapon_textures(Secondary_weapon_to_weapon_info[PROXIMITY_INDEX]);
512 case POW_HOMING_AMMO_1:
513 case POW_HOMING_AMMO_4:
514 ogl_cache_weapon_textures(Primary_weapon_to_weapon_info[HOMING_INDEX]);
516 case POW_SMARTBOMB_WEAPON:
517 ogl_cache_weapon_textures(Secondary_weapon_to_weapon_info[SMART_INDEX]);
519 case POW_MEGA_WEAPON:
520 ogl_cache_weapon_textures(Secondary_weapon_to_weapon_info[MEGA_INDEX]);
524 else if(Objects[i].render_type==RT_POLYOBJ){
525 //printf("robot %i model %i rmodel %i\n", Objects[i].id, Objects[i].rtype.pobj_info.model_num, Robot_info[Objects[i].id].model_num);
526 if (Objects[i].type == OBJ_ROBOT)
528 ogl_cache_vclipn_textures(Robot_info[Objects[i].id].exp1_vclip_num);
529 ogl_cache_vclipn_textures(Robot_info[Objects[i].id].exp2_vclip_num);
530 ogl_cache_weapon_textures(Robot_info[Objects[i].id].weapon_type);
532 if (Objects[i].rtype.pobj_info.tmap_override != -1)
533 ogl_loadbmtexture(&GameBitmaps[Textures[Objects[i].rtype.pobj_info.tmap_override].index]);
535 ogl_cache_polymodel_textures(Objects[i].rtype.pobj_info.model_num);
539 glmprintf((0,"finished caching\n"));
540 r_cachedtexcount = r_texcount;
543 int r_polyc,r_tpolyc,r_bitmapc,r_ubitmapc,r_ubitbltc,r_upixelc;
544 #define f2glf(x) (f2fl(x))
546 bool g3_draw_line(g3s_point *p0,g3s_point *p1)
549 c=grd_curcanv->cv_color;
550 OGL_DISABLE(TEXTURE_2D);
551 glColor3f(PAL2Tr(c),PAL2Tg(c),PAL2Tb(c));
553 glVertex3f(f2glf(p0->p3_vec.x),f2glf(p0->p3_vec.y),-f2glf(p0->p3_vec.z));
554 glVertex3f(f2glf(p1->p3_vec.x),f2glf(p1->p3_vec.y),-f2glf(p1->p3_vec.z));
558 void ogl_drawcircle2(int nsides,int type,float xsc,float xo,float ysc,float yo){
562 for (i=0; i<nsides; i++) {
563 ang = 2.0*M_PI*i/nsides;
564 glVertex2f(cosf(ang)*xsc+xo,sinf(ang)*ysc+yo);
568 void ogl_drawcircle(int nsides,int type){
572 for (i=0; i<nsides; i++) {
573 ang = 2.0*M_PI*i/nsides;
574 glVertex2f(cosf(ang),sinf(ang));
578 int circle_list_init(int nsides,int type,int mode) {
579 int hand=glGenLists(1);
580 glNewList(hand, mode);
581 /* draw a unit radius circle in xy plane centered on origin */
582 ogl_drawcircle(nsides,type);
586 float bright_g[4]={ 32.0/256, 252.0/256, 32.0/256};
587 float dark_g[4]={ 32.0/256, 148.0/256, 32.0/256};
588 float darker_g[4]={ 32.0/256, 128.0/256, 32.0/256};
589 void ogl_draw_reticle(int cross,int primary,int secondary){
590 float scale=(float)Canvas_height/(float)grd_curscreen->sc_h;
592 // glTranslatef(0.5,0.5,0);
593 glTranslatef((grd_curcanv->cv_bitmap.bm_w/2+grd_curcanv->cv_bitmap.bm_x)/(float)last_width,1.0-(grd_curcanv->cv_bitmap.bm_h/2+grd_curcanv->cv_bitmap.bm_y)/(float)last_height,0);
594 glScalef(scale/320.0,scale/200.0,scale);//the positions are based upon the standard reticle at 320x200 res.
596 OGL_DISABLE(TEXTURE_2D);
598 if (!cross_lh[cross]){
599 cross_lh[cross]=glGenLists(1);
600 glNewList(cross_lh[cross], GL_COMPILE_AND_EXECUTE);
603 glColor3fv(darker_g);
604 glVertex2f(-4.0,4.0);
606 glColor3fv(bright_g);
609 glVertex2f(-2.0,2.0);
613 glVertex2f(-3.0,-2.0);
615 glColor3fv(bright_g);
616 glVertex2f(-2.0,-1.0);
619 glColor3fv(darker_g);
622 glColor3fv(bright_g);
629 glVertex2f(3.0,-2.0);
631 glColor3fv(bright_g);
632 glVertex2f(2.0,-1.0);
637 glCallList(cross_lh[cross]);
639 // if (Canvas_height>200)
640 // glLineWidth(Canvas_height/(float)200);
641 if (!primary_lh[primary]){
642 primary_lh[primary]=glGenLists(1);
643 glNewList(primary_lh[primary], GL_COMPILE_AND_EXECUTE);
648 glVertex2f(-14.0,-8.0);
649 glVertex2f(-8.0,-5.0);
651 glVertex2f(14.0,-8.0);
652 glVertex2f(8.0,-5.0);
657 glColor3fv(bright_g);
659 ogl_drawcircle2(6,GL_POLYGON,1.5,-7.0,1.5,-5.0);
661 ogl_drawcircle2(6,GL_POLYGON,1.5,7.0,1.5,-5.0);
665 glColor3fv(bright_g);
667 ogl_drawcircle2(4,GL_POLYGON,1.0,-14.0,1.0,-8.0);
669 ogl_drawcircle2(4,GL_POLYGON,1.0,14.0,1.0,-8.0);
673 glCallList(primary_lh[primary]);
674 // if (Canvas_height>200)
677 if (!secondary_lh[secondary]){
678 secondary_lh[secondary]=glGenLists(1);
679 glNewList(secondary_lh[secondary], GL_COMPILE_AND_EXECUTE);
683 glColor3fv(darker_g);
685 glColor3fv(bright_g);
686 ogl_drawcircle2(8,GL_LINE_LOOP,2.0,-10.0,2.0,-1.0);
689 glColor3fv(darker_g);
691 glColor3fv(bright_g);
692 ogl_drawcircle2(8,GL_LINE_LOOP,2.0,10.0,2.0,-1.0);
694 //bottom/middle secondary
696 glColor3fv(darker_g);
698 glColor3fv(bright_g);
699 ogl_drawcircle2(8,GL_LINE_LOOP,2.0,0.0,2.0,-7.0);
703 glCallList(secondary_lh[secondary]);
707 int g3_draw_sphere(g3s_point *pnt,fix rad){
709 c=grd_curcanv->cv_color;
710 OGL_DISABLE(TEXTURE_2D);
711 // glPointSize(f2glf(rad));
712 glColor3f(CPAL2Tr(c),CPAL2Tg(c),CPAL2Tb(c));
713 // glBegin(GL_POINTS);
714 // glVertex3f(f2glf(pnt->p3_vec.x),f2glf(pnt->p3_vec.y),-f2glf(pnt->p3_vec.z));
717 glTranslatef(f2glf(pnt->p3_vec.x),f2glf(pnt->p3_vec.y),-f2glf(pnt->p3_vec.z));
718 glScalef(f2glf(rad),f2glf(rad),f2glf(rad));
719 if (!sphereh) sphereh=circle_list_init(20,GL_POLYGON,GL_COMPILE_AND_EXECUTE);
720 else glCallList(sphereh);
725 int gr_ucircle(fix xc1, fix yc1, fix r1)
728 c=grd_curcanv->cv_color;
729 OGL_DISABLE(TEXTURE_2D);
730 glColor3f(CPAL2Tr(c),CPAL2Tg(c),CPAL2Tb(c));
733 (f2fl(xc1) + grd_curcanv->cv_bitmap.bm_x + 0.5) / (float)last_width,
734 1.0 - (f2fl(yc1) + grd_curcanv->cv_bitmap.bm_y + 0.5) / (float)last_height,0);
735 glScalef(f2fl(r1) / last_width, f2fl(r1) / last_height, 1.0);
736 ogl_drawcircle(10 + 2 * (int)(M_PI * f2fl(r1) / 19), GL_LINE_LOOP);
740 int gr_circle(fix xc1,fix yc1,fix r1){
741 return gr_ucircle(xc1,yc1,r1);
744 bool g3_draw_poly(int nv,g3s_point **pointlist)
748 c=grd_curcanv->cv_color;
749 // glColor3f((gr_palette[c*3]+gr_palette_gamma)/63.0,(gr_palette[c*3+1]+gr_palette_gamma)/63.0,(gr_palette[c*3+2]+gr_palette_gamma)/63.0);
750 OGL_DISABLE(TEXTURE_2D);
751 if (Gr_scanline_darkening_level >= GR_FADE_LEVELS)
752 glColor3f(PAL2Tr(c), PAL2Tg(c), PAL2Tb(c));
754 glColor4f(PAL2Tr(c), PAL2Tg(c), PAL2Tb(c), 1.0 - (float)Gr_scanline_darkening_level / ((float)GR_FADE_LEVELS - 1.0));
755 glBegin(GL_TRIANGLE_FAN);
757 // glVertex3f(f2glf(pointlist[c]->p3_vec.x),f2glf(pointlist[c]->p3_vec.y),f2glf(pointlist[c]->p3_vec.z));
758 glVertex3f(f2glf(pointlist[c]->p3_vec.x),f2glf(pointlist[c]->p3_vec.y),-f2glf(pointlist[c]->p3_vec.z));
764 void gr_upoly_tmap(int nverts, int *vert ){
765 mprintf((0,"gr_upoly_tmap: unhandled\n"));//should never get called
767 void draw_tmap_flat(grs_bitmap *bm,int nv,g3s_point **vertlist){
768 mprintf((0,"draw_tmap_flat: unhandled\n"));//should never get called
770 extern void (*tmap_drawer_ptr)(grs_bitmap *bm,int nv,g3s_point **vertlist);
771 bool g3_draw_tmap(int nv,g3s_point **pointlist,g3s_uvl *uvl_list,grs_bitmap *bm)
775 if (tmap_drawer_ptr==draw_tmap_flat){
776 /* fix average_light=0;
779 average_light += uvl_list[i].l;*/
780 OGL_DISABLE(TEXTURE_2D);
781 // glmprintf((0,"Gr_scanline_darkening_level=%i %f\n",Gr_scanline_darkening_level,Gr_scanline_darkening_level/(float)NUM_LIGHTING_LEVELS));
782 glColor4f(0,0,0,1.0-(Gr_scanline_darkening_level/(float)NUM_LIGHTING_LEVELS));
783 //glColor4f(0,0,0,f2fl(average_light/nv));
784 glBegin(GL_TRIANGLE_FAN);
786 // glColor4f(0,0,0,f2fl(uvl_list[c].l));
787 // glTexCoord2f(f2glf(uvl_list[c].u),f2glf(uvl_list[c].v));
788 glVertex3f(f2glf(pointlist[c]->p3_vec.x),f2glf(pointlist[c]->p3_vec.y),-f2glf(pointlist[c]->p3_vec.z));
791 }else if (tmap_drawer_ptr==draw_tmap){
793 /* if (bm->bm_w !=64||bm->bm_h!=64)
794 printf("g3_draw_tmap w %i h %i\n",bm->bm_w,bm->bm_h);*/
795 OGL_ENABLE(TEXTURE_2D);
797 ogl_texwrap(bm->gltexture,GL_REPEAT);
798 glBegin(GL_TRIANGLE_FAN);
800 if (bm->bm_flags&BM_FLAG_NO_LIGHTING){
803 //l=f2fl(uvl_list[c].l)+gr_palette_gamma/63.0;
804 l=f2fl(uvl_list[c].l);
807 glTexCoord2f(f2glf(uvl_list[c].u),f2glf(uvl_list[c].v));
808 //glVertex3f(f2glf(pointlist[c]->p3_vec.x),f2glf(pointlist[c]->p3_vec.y),f2glf(pointlist[c]->p3_vec.z));
809 glVertex3f(f2glf(pointlist[c]->p3_vec.x),f2glf(pointlist[c]->p3_vec.y),-f2glf(pointlist[c]->p3_vec.z));
813 mprintf((0,"g3_draw_tmap: unhandled tmap_drawer %p\n",tmap_drawer_ptr));
818 int active_texture_unit = 0;
820 void ogl_setActiveTexture(int t)
822 if (ogl_arb_multitexture_ok)
824 #ifdef GL_ARB_multitexture
826 glActiveTextureARB(GL_TEXTURE0_ARB);
828 glActiveTextureARB(GL_TEXTURE1_ARB);
831 else if (ogl_sgis_multitexture_ok)
833 #ifdef GL_SGIS_multitexture
835 glSelectTextureSGIS(GL_TEXTURE0_SGIS);
837 glSelectTextureSGIS(GL_TEXTURE1_SGIS);
840 active_texture_unit = t;
843 void ogl_MultiTexCoord2f(int t, float u, float v)
845 if (ogl_arb_multitexture_ok)
847 #ifdef GL_ARB_multitexture
849 glMultiTexCoord2fARB(GL_TEXTURE0_ARB, u, v);
851 glMultiTexCoord2fARB(GL_TEXTURE1_ARB, u, v);
854 else if (ogl_sgis_multitexture_ok)
856 #ifdef GL_SGIS_multitexture
858 glMultiTexCoord2fSGIS(GL_TEXTURE0_SGIS, u, v);
860 glMultiTexCoord2fSGIS(GL_TEXTURE1_SGIS, u, v);
865 bool g3_draw_tmap_2(int nv, g3s_point **pointlist, g3s_uvl *uvl_list, grs_bitmap *bmbot, grs_bitmap *bm, int orient)
867 #if ((defined(GL_NV_register_combiners) || defined(GL_NV_texture_env_combine4)) && (defined(GL_ARB_multitexture) || defined(GL_SGIS_multitexture)))
868 if ((/*ogl_nv_register_combiners_ok ||*/ ogl_nv_texture_env_combine4_ok) && (ogl_arb_multitexture_ok || ogl_sgis_multitexture_ok))
873 if (tmap_drawer_ptr != draw_tmap)
878 //ogl_setActiveTexture(0);
879 OGL_ENABLE(TEXTURE_2D);
880 ogl_bindbmtex(bmbot);
881 ogl_texwrap(bmbot->gltexture, GL_REPEAT);
882 // GL_MODULATE is fine for texture 0
884 ogl_setActiveTexture(1);
885 glEnable(GL_TEXTURE_2D);
887 ogl_texwrap(bm->gltexture,GL_REPEAT);
889 #ifdef GL_NV_register_combiners
890 if (ogl_nv_register_combiners_ok)
892 glEnable(GL_REGISTER_COMBINERS_NV);
893 glCombinerParameteriNV(GL_NUM_GENERAL_COMBINERS_NV, 1);
894 // spare0 = tex0 * (1-alpha1) + tex1 * alpha1
895 glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_A_NV, GL_TEXTURE0_ARB, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
896 glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_B_NV, GL_TEXTURE1_ARB, GL_UNSIGNED_INVERT_NV, GL_ALPHA);
897 glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_C_NV, GL_TEXTURE1_ARB, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
898 glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_D_NV, GL_TEXTURE1_ARB, GL_UNSIGNED_IDENTITY_NV, GL_ALPHA);
900 GL_COMBINER0_NV, //GLenum stage
901 GL_RGB, //GLenum portion,
902 GL_DISCARD_NV, //GLenum abOutput,
903 GL_DISCARD_NV, //GLenum cdOutput,
904 GL_SPARE0_NV, //GLenum sumOutput,
905 GL_NONE, //GLenum scale,
906 GL_NONE, //GLenum bias,
907 GL_FALSE, //GLboolean abDotProduct,
908 GL_FALSE, //GLboolean cdDotProduct,
909 GL_FALSE //GLboolean muxSum
911 // out = spare0 * color
912 // ( out = AB + (1-A)C + D )
913 glFinalCombinerInputNV(GL_VARIABLE_A_NV, GL_SPARE0_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
914 glFinalCombinerInputNV(GL_VARIABLE_B_NV, GL_PRIMARY_COLOR_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
915 glFinalCombinerInputNV(GL_VARIABLE_C_NV, GL_ZERO, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
916 glFinalCombinerInputNV(GL_VARIABLE_D_NV, GL_ZERO, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
918 if (bm->bm_flags & BM_FLAG_SUPER_TRANSPARENT)
920 // out = alpha0*(1-tex1) + alpha1
921 glCombinerInputNV(GL_COMBINER0_NV, GL_ALPHA, GL_VARIABLE_A_NV, GL_TEXTURE0_ARB, GL_UNSIGNED_IDENTITY_NV, GL_ALPHA);
922 glCombinerInputNV(GL_COMBINER0_NV, GL_ALPHA, GL_VARIABLE_B_NV, GL_TEXTURE1_ARB, GL_UNSIGNED_INVERT_NV, GL_BLUE);
923 glCombinerInputNV(GL_COMBINER0_NV, GL_ALPHA, GL_VARIABLE_C_NV, GL_TEXTURE1_ARB, GL_UNSIGNED_IDENTITY_NV, GL_ALPHA);
924 glCombinerInputNV(GL_COMBINER0_NV, GL_ALPHA, GL_VARIABLE_D_NV, GL_ZERO, GL_UNSIGNED_INVERT_NV, GL_ALPHA);
928 // out = alpha0 + alpha1
929 glCombinerInputNV(GL_COMBINER0_NV, GL_ALPHA, GL_VARIABLE_A_NV, GL_TEXTURE0_ARB, GL_UNSIGNED_IDENTITY_NV, GL_ALPHA);
930 glCombinerInputNV(GL_COMBINER0_NV, GL_ALPHA, GL_VARIABLE_B_NV, GL_ZERO, GL_UNSIGNED_INVERT_NV, GL_ALPHA);
931 glCombinerInputNV(GL_COMBINER0_NV, GL_ALPHA, GL_VARIABLE_C_NV, GL_TEXTURE1_ARB, GL_UNSIGNED_IDENTITY_NV, GL_ALPHA);
932 glCombinerInputNV(GL_COMBINER0_NV, GL_ALPHA, GL_VARIABLE_D_NV, GL_ZERO, GL_UNSIGNED_INVERT_NV, GL_ALPHA);
935 GL_COMBINER0_NV, //GLenum stage
936 GL_ALPHA, //GLenum portion,
937 GL_DISCARD_NV, //GLenum abOutput,
938 GL_DISCARD_NV, //GLenum cdOutput,
939 GL_SPARE0_NV, //GLenum sumOutput,
940 GL_NONE, //GLenum scale,
941 GL_NONE, //GLenum bias,
942 GL_FALSE, //GLboolean abDotProduct,
943 GL_FALSE, //GLboolean cdDotProduct,
944 GL_FALSE //GLboolean muxSum
946 glFinalCombinerInputNV(GL_VARIABLE_G_NV, GL_SPARE0_NV, GL_UNSIGNED_IDENTITY_NV, GL_ALPHA);
951 //http://oss.sgi.com/projects/ogl-sample/registry/NV/texture_env_combine4.txt
952 //only GL_NV_texture_env_combine4 lets us do what we need:
953 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE4_NV);
955 //multiply top texture by color(vertex lighting) and add bottom texture(where alpha says to)
956 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_ADD);
958 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE);
959 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PRIMARY_COLOR_EXT);
960 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_EXT, GL_TEXTURE);
961 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE3_RGB_NV, GL_PREVIOUS_EXT);
963 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, GL_SRC_COLOR);
964 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_EXT, GL_SRC_COLOR);
965 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_EXT, GL_ONE_MINUS_SRC_ALPHA);
966 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND3_RGB_NV, GL_SRC_COLOR);
968 //add up alpha channels
969 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_ADD);
971 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_TEXTURE);
972 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_EXT, GL_ZERO);
973 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA_EXT, GL_PREVIOUS_EXT);
974 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE3_ALPHA_NV, GL_ZERO);
976 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT, GL_SRC_ALPHA);
977 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_EXT, GL_ONE_MINUS_SRC_ALPHA);
978 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA_EXT, GL_SRC_ALPHA);
979 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND3_ALPHA_NV, GL_ONE_MINUS_SRC_ALPHA);
982 // GL_DECAL works sorta ok but the top texture is fullbright.
983 //glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
985 // GL_ARB_texture_env_combine comes close, but doesn't quite make it.
986 //glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
988 //// this gives effect like GL_DECAL:
989 //glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_INTERPOLATE);
990 //glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
991 //glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB);
992 //glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_TEXTURE);
995 // this properly shades the top texture, but the bottom texture doesn't get through.
996 //glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
997 //glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PRIMARY_COLOR_ARB);
998 //glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE);
1002 //glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_ADD);
1003 //glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
1004 //glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_PREVIOUS_ARB);
1006 glBegin(GL_TRIANGLE_FAN);
1010 u1=1.0-f2glf(uvl_list[c].v);
1011 v1=f2glf(uvl_list[c].u);
1014 u1=1.0-f2glf(uvl_list[c].u);
1015 v1=1.0-f2glf(uvl_list[c].v);
1018 u1=f2glf(uvl_list[c].v);
1019 v1=1.0-f2glf(uvl_list[c].u);
1022 u1=f2glf(uvl_list[c].u);
1023 v1=f2glf(uvl_list[c].v);
1026 if (bm->bm_flags&BM_FLAG_NO_LIGHTING){
1029 l=f2fl(uvl_list[c].l);
1032 ogl_MultiTexCoord2f(0, f2glf(uvl_list[c].u), f2glf(uvl_list[c].v));
1033 ogl_MultiTexCoord2f(1, u1, v1);
1034 //glVertex3f(f2glf(pointlist[c]->p3_vec.x),f2glf(pointlist[c]->p3_vec.y),f2glf(pointlist[c]->p3_vec.z));
1035 //glVertex3f(f2glf(pointlist[c]->p3_vec.x),f2glf(pointlist[c]->p3_vec.y),f2glf(pointlist[c]->p3_vec.z));
1036 glVertex3f(f2glf(pointlist[c]->p3_vec.x),f2glf(pointlist[c]->p3_vec.y),-f2glf(pointlist[c]->p3_vec.z));
1039 //ogl_setActiveTexture(1); // still the active texture
1040 #ifdef GL_NV_register_combiners
1041 if (ogl_nv_register_combiners_ok)
1043 glDisable(GL_REGISTER_COMBINERS_NV);
1048 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
1050 glDisable(GL_TEXTURE_2D);
1051 ogl_setActiveTexture(0);
1059 g3_draw_tmap(nv,pointlist,uvl_list,bmbot);//draw the bottom texture first.. could be optimized with multitexturing..
1062 /* if (bm->bm_w !=64||bm->bm_h!=64)
1063 printf("g3_draw_tmap w %i h %i\n",bm->bm_w,bm->bm_h);*/
1064 OGL_ENABLE(TEXTURE_2D);
1066 ogl_texwrap(bm->gltexture,GL_REPEAT);
1067 glBegin(GL_TRIANGLE_FAN);
1071 u1=1.0-f2glf(uvl_list[c].v);
1072 v1=f2glf(uvl_list[c].u);
1075 u1=1.0-f2glf(uvl_list[c].u);
1076 v1=1.0-f2glf(uvl_list[c].v);
1079 u1=f2glf(uvl_list[c].v);
1080 v1=1.0-f2glf(uvl_list[c].u);
1083 u1=f2glf(uvl_list[c].u);
1084 v1=f2glf(uvl_list[c].v);
1087 if (bm->bm_flags&BM_FLAG_NO_LIGHTING){
1090 //l=f2fl(uvl_list[c].l)+gr_palette_gamma/63.0;
1091 l=f2fl(uvl_list[c].l);
1094 glTexCoord2f(u1,v1);
1095 //glVertex3f(f2glf(pointlist[c]->p3_vec.x),f2glf(pointlist[c]->p3_vec.y),f2glf(pointlist[c]->p3_vec.z));
1096 //glVertex3f(f2glf(pointlist[c]->p3_vec.x),f2glf(pointlist[c]->p3_vec.y),f2glf(pointlist[c]->p3_vec.z));
1097 glVertex3f(f2glf(pointlist[c]->p3_vec.x),f2glf(pointlist[c]->p3_vec.y),-f2glf(pointlist[c]->p3_vec.z));
1104 bool g3_draw_bitmap(vms_vector *pos,fix width,fix height,grs_bitmap *bm, int orientation)
1107 vms_vector pv,v1;//,v2;
1111 // printf("g3_draw_bitmap: %f,%f,%f - ",f2glf(pos->x),f2glf(pos->y),-f2glf(pos->z));
1112 // printf("(%f,%f,%f) ",f2glf(View_position.x),f2glf(View_position.y),-f2glf(View_position.z));
1114 OGL_ENABLE(TEXTURE_2D);
1116 ogl_texwrap(bm->gltexture,GL_CLAMP);
1119 glColor3f(1.0,1.0,1.0);
1120 width = fixmul(width,Matrix_scale.x);
1121 height = fixmul(height,Matrix_scale.y);
1123 // g3_rotate_point(&p[i],pos);
1124 vm_vec_sub(&v1,pos,&View_position);
1125 vm_vec_rotate(&pv,&v1,&View_matrix);
1126 // printf(" %f,%f,%f->",f2glf(pv.x),f2glf(pv.y),-f2glf(pv.z));
1129 glTexCoord2f(0.0, 0.0);
1134 glTexCoord2f(bm->gltexture->u, 0.0);
1139 glTexCoord2f(bm->gltexture->u, bm->gltexture->v);
1144 glTexCoord2f(0.0, bm->gltexture->v);
1149 // vm_vec_rotate(&v2,&v1,&View_matrix);
1150 // vm_vec_sub(&v1,&v2,&pv);
1151 //vm_vec_sub(&v1,&pv,&v2);
1152 // vm_vec_sub(&v2,&pv,&v1);
1153 glVertex3f(f2glf(pv.x),f2glf(pv.y),-f2glf(pv.z));
1154 // printf("%f,%f,%f ",f2glf(v1.x),f2glf(v1.y),-f2glf(v1.z));
1162 bool ogl_ubitmapm_c(int x, int y,grs_bitmap *bm,int c)
1164 GLfloat xo,yo,xf,yf;
1165 GLfloat u1,u2,v1,v2;
1167 x+=grd_curcanv->cv_bitmap.bm_x;
1168 y+=grd_curcanv->cv_bitmap.bm_y;
1169 xo=x/(float)last_width;
1170 xf=(bm->bm_w+x)/(float)last_width;
1171 yo=1.0-y/(float)last_height;
1172 yf=1.0-(bm->bm_h+y)/(float)last_height;
1174 // printf("g3_draw_bitmap: %f,%f,%f - ",f2glf(pos->x),f2glf(pos->y),-f2glf(pos->z));
1175 // printf("(%f,%f,%f) ",f2glf(View_position.x),f2glf(View_position.y),-f2glf(View_position.z));
1177 /* glEnABLE(ALPHA_TEST);
1178 glAlphaFunc(GL_GREATER,0.0);*/
1180 OGL_ENABLE(TEXTURE_2D);
1182 ogl_texwrap(bm->gltexture,GL_CLAMP);
1186 if (bm->bm_w==bm->gltexture->w)
1187 u2=bm->gltexture->u;
1189 u2=(bm->bm_w+bm->bm_x)/(float)bm->gltexture->tw;
1191 u1=bm->bm_x/(float)bm->gltexture->tw;
1192 u2=(bm->bm_w+bm->bm_x)/(float)bm->gltexture->tw;
1196 if (bm->bm_h==bm->gltexture->h)
1197 v2=bm->gltexture->v;
1199 v2=(bm->bm_h+bm->bm_y)/(float)bm->gltexture->th;
1201 v1=bm->bm_y/(float)bm->gltexture->th;
1202 v2=(bm->bm_h+bm->bm_y)/(float)bm->gltexture->th;
1207 glColor3f(1.0,1.0,1.0);
1209 glColor3f(CPAL2Tr(c),CPAL2Tg(c),CPAL2Tb(c));
1210 glTexCoord2f(u1, v1); glVertex2f(xo, yo);
1211 glTexCoord2f(u2, v1); glVertex2f(xf, yo);
1212 glTexCoord2f(u2, v2); glVertex2f(xf, yf);
1213 glTexCoord2f(u1, v2); glVertex2f(xo, yf);
1215 // glDisABLE(ALPHA_TEST);
1219 bool ogl_ubitmapm(int x, int y,grs_bitmap *bm){
1220 return ogl_ubitmapm_c(x,y,bm,-1);
1221 // return ogl_ubitblt(bm->bm_w,bm->bm_h,x,y,0,0,bm,NULL);
1224 //also upsidedown, currently.
1225 bool ogl_ubitblt(int w,int h,int dx,int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest)
1227 GLfloat xo,yo;//,xs,ys;
1228 glmprintf((0,"ogl_ubitblt(w=%i,h=%i,dx=%i,dy=%i,sx=%i,sy=%i,src=%p,dest=%p\n",w,h, dx, dy,sx, sy, src,dest));
1233 xo=dx/(float)last_width;
1234 // xo=dx/(float)grd_curscreen->sc_w;
1235 // xs=w/(float)last_width;
1236 //yo=1.0-dy/(float)last_height;
1237 yo=1.0-(dy+h)/(float)last_height;
1238 // ys=h/(float)last_height;
1240 // OGL_ENABLE(TEXTURE_2D);
1242 OGL_DISABLE(TEXTURE_2D);
1243 glRasterPos2f(xo,yo);
1244 ogl_filltexbuf(src->bm_data,texbuf,src->bm_w,w,h,sx,sy,w,h,GL_RGBA);
1245 glDrawPixels(w,h,GL_RGBA,GL_UNSIGNED_BYTE,texbuf);
1251 bool ogl_ubitblt_i(int dw,int dh,int dx,int dy, int sw, int sh, int sx, int sy, grs_bitmap * src, grs_bitmap * dest)
1253 GLfloat xo,yo,xs,ys;
1254 GLfloat u1,v1;//,u2,v2;
1256 // unsigned char *oldpal;
1259 ogl_init_texture(&tex, sw, sh, OGL_FLAG_ALPHA);
1261 tex.lw=src->bm_rowsize;
1263 /* if (w==src->bm_w && sx==0){
1266 u1=sx/(float)src->bm_w*src->glu;
1267 u2=w/(float)src->bm_w*src->glu+u1;
1269 if (h==src->bm_h && sy==0){
1272 v1=sy/(float)src->bm_h*src->glv;
1273 v2=h/(float)src->bm_h*src->glv+v1;
1279 xo=dx/(float)last_width;
1280 xs=dw/(float)last_width;
1281 yo=1.0-dy/(float)last_height;
1282 ys=dh/(float)last_height;
1284 OGL_ENABLE(TEXTURE_2D);
1287 ogl_pal=gr_current_pal;
1288 ogl_loadtexture(src->bm_data, sx, sy, &tex, src->bm_flags, 0);
1291 OGL_BINDTEXTURE(tex.handle);
1293 ogl_texwrap(&tex,GL_CLAMP);
1296 glColor3f(1.0,1.0,1.0);
1297 glTexCoord2f(u1, v1); glVertex2f(xo, yo);
1298 glTexCoord2f(tex.u, v1); glVertex2f(xo+xs, yo);
1299 glTexCoord2f(tex.u, tex.v); glVertex2f(xo+xs, yo-ys);
1300 glTexCoord2f(u1, tex.v); glVertex2f(xo, yo-ys);
1302 ogl_freetexture(&tex);
1305 bool ogl_ubitblt(int w,int h,int dx,int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest){
1306 return ogl_ubitblt_i(w,h,dx,dy,w,h,sx,sy,src,dest);
1309 bool ogl_ubitblt_tolinear(int w,int h,int dx,int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest){
1311 unsigned char *d,*s;
1315 w1=grd_curscreen->sc_w;h1=grd_curscreen->sc_h;
1316 if (w1*h1*3>OGLTEXBUFSIZE)
1317 Error("ogl_ubitblt_tolinear: screen res larger than OGLTEXBUFSIZE\n");
1319 if (ogl_readpixels_ok>0){
1320 OGL_DISABLE(TEXTURE_2D);
1321 glReadBuffer(GL_FRONT);
1322 glReadPixels(0,0,w1,h1,GL_RGB,GL_UNSIGNED_BYTE,texbuf);
1323 // glReadPixels(sx,grd_curscreen->sc_h-(sy+h),w,h,GL_RGB,GL_UNSIGNED_BYTE,texbuf);
1324 // glReadPixels(sx,sy,w+sx,h+sy,GL_RGB,GL_UNSIGNED_BYTE,texbuf);
1326 memset(texbuf,0,w1*h1*3);
1330 d=dest->bm_data+dx+(dy+i)*dest->bm_rowsize;
1331 s=texbuf+((h1-(i+sy+1))*w1+sx)*3;
1333 *d=gr_find_closest_color(s[0]/4,s[1]/4,s[2]/4);
1340 unsigned char *d,*s,*e;
1341 if (w*h*3>OGLTEXBUFSIZE)
1342 Error("ogl_ubitblt_tolinear: size larger than OGLTEXBUFSIZE\n");
1345 #if 1//also seems to cause a mess. need to look into it a bit more..
1346 if (ogl_readpixels_ok>0){
1347 OGL_DISABLE(TEXTURE_2D);
1348 glReadBuffer(GL_FRONT);
1349 // glReadPixels(0,0,w,h,GL_RGB,GL_UNSIGNED_BYTE,texbuf);
1350 glReadPixels(sx,grd_curscreen->sc_h-(sy+h),w,h,GL_RGB,GL_UNSIGNED_BYTE,texbuf);
1353 memset(texbuf,0,w*h*3);
1354 // d=dest->bm_data+dx+(dy+i)*dest->bm_rowsize;
1355 d=dest->bm_data+dx+dy*dest->bm_rowsize;
1357 s=texbuf+w*(h-(i+1))*3;
1359 if (s<texbuf){Error("blah1\n");}
1360 if (d<dest->bm_data){Error("blah3\n");}
1361 // d=dest->bm_data+(i*dest->bm_rowsize);
1365 if (s>texbuf+w*h*3-3){Error("blah2\n");}
1366 if (d>dest->bm_data+dest->bm_rowsize*(h+dy)+dx ){Error("blah4\n");}
1367 *d=gr_find_closest_color(s[0]/4,s[1]/4,s[2]/4);
1373 d+=dest->bm_rowsize;
1375 glmprintf((0,"c=%i w*h=%i\n",c,w*h));
1380 bool ogl_ubitblt_copy(int w,int h,int dx,int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest){
1381 #if 0 //just seems to cause a mess.
1382 GLfloat xo,yo;//,xs,ys;
1387 // xo=dx/(float)last_width;
1388 xo=dx/(float)grd_curscreen->sc_w;
1389 // yo=1.0-(dy+h)/(float)last_height;
1390 yo=1.0-(dy+h)/(float)grd_curscreen->sc_h;
1393 OGL_DISABLE(TEXTURE_2D);
1394 glReadBuffer(GL_FRONT);
1395 glRasterPos2f(xo,yo);
1396 // glReadPixels(0,0,w,h,GL_RGB,GL_UNSIGNED_BYTE,texbuf);
1397 glCopyPixels(sx,grd_curscreen->sc_h-(sy+h),w,h,GL_COLOR);
1403 grs_canvas *offscreen_save_canv = NULL, *offscreen_canv = NULL;
1405 void ogl_start_offscreen_render(int x, int y, int w, int h)
1408 Error("ogl_start_offscreen_render: offscreen_canv!=NULL");
1409 offscreen_save_canv = grd_curcanv;
1410 offscreen_canv = gr_create_sub_canvas(grd_curcanv, x, y, w, h);
1411 gr_set_current_canvas(offscreen_canv);
1412 glDrawBuffer(GL_BACK);
1414 void ogl_end_offscreen_render(void)
1418 if (!offscreen_canv)
1419 Error("ogl_end_offscreen_render: no offscreen_canv");
1421 glDrawBuffer(GL_FRONT);
1422 glReadBuffer(GL_BACK);
1423 OGL_DISABLE(TEXTURE_2D);
1425 y = last_height - offscreen_canv->cv_bitmap.bm_y - offscreen_canv->cv_bitmap.bm_h;
1426 glRasterPos2f(offscreen_canv->cv_bitmap.bm_x/(float)last_width, y/(float)last_height);
1427 glCopyPixels(offscreen_canv->cv_bitmap.bm_x, y,
1428 offscreen_canv->cv_bitmap.bm_w,
1429 offscreen_canv->cv_bitmap.bm_h, GL_COLOR);
1431 gr_free_sub_canvas(offscreen_canv);
1432 gr_set_current_canvas(offscreen_save_canv);
1433 offscreen_canv=NULL;
1436 void ogl_start_frame(void){
1437 r_polyc=0;r_tpolyc=0;r_bitmapc=0;r_ubitmapc=0;r_ubitbltc=0;r_upixelc=0;
1438 // gl_badtexture=500;
1440 OGL_VIEWPORT(grd_curcanv->cv_bitmap.bm_x,grd_curcanv->cv_bitmap.bm_y,Canvas_width,Canvas_height);
1441 glClearColor(0.0, 0.0, 0.0, 0.0);
1442 // glEnable(GL_ALPHA_TEST);
1443 // glAlphaFunc(GL_GREATER,0.01);
1444 glShadeModel(GL_SMOOTH);
1445 glMatrixMode(GL_PROJECTION);
1446 glLoadIdentity();//clear matrix
1447 //gluPerspective(90.0,(GLfloat)(grd_curscreen->sc_w*3)/(GLfloat)(grd_curscreen->sc_h*4),1.0,1000000.0);
1448 //gluPerspective(90.0,(GLfloat)(grd_curscreen->sc_w*3)/(GLfloat)(grd_curscreen->sc_h*4),0.01,1000000.0);
1449 gluPerspective(90.0,1.0,0.01,1000000.0);
1450 //gluPerspective(90.0,(GLfloat)(Canvas_width*3)/(GLfloat)(Canvas_height*4),0.01,1000000.0);
1451 // gluPerspective(75.0,(GLfloat)Canvas_width/(GLfloat)Canvas_height,1.0,1000000.0);
1452 glMatrixMode(GL_MODELVIEW);
1453 glLoadIdentity();//clear matrix
1455 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1456 // glDisABLE(DITHER);
1457 // glScalef(1.0,1.0,-1.0);
1458 // glScalef(1.0,1.0,-1.0);
1461 // glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
1462 // OGL_TEXENV(GL_TEXTURE_ENV_MODE,GL_MODULATE);
1463 // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_texmagfilt);
1464 // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_texminfilt);
1465 // OGL_TEXPARAM(GL_TEXTURE_MAG_FILTER,GL_texmagfilt);
1466 // OGL_TEXPARAM(GL_TEXTURE_MIN_FILTER,GL_texminfilt);
1467 // glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1468 // glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1471 void merge_textures_stats(void);
1473 void ogl_end_frame(void){
1474 // OGL_VIEWPORT(grd_curcanv->cv_bitmap.bm_x,grd_curcanv->cv_bitmap.bm_y,);
1475 OGL_VIEWPORT(0,0,grd_curscreen->sc_w,grd_curscreen->sc_h);
1477 // merge_textures_stats();
1478 // ogl_texture_stats();
1480 // glViewport(0,0,grd_curscreen->sc_w,grd_curscreen->sc_h);
1481 glMatrixMode(GL_PROJECTION);
1482 glLoadIdentity();//clear matrix
1483 glOrtho(0.0, 1.0, 0.0, 1.0, -1.0, 1.0);
1484 glMatrixMode(GL_MODELVIEW);
1485 glLoadIdentity();//clear matrix
1486 // glDisABLE(BLEND);
1487 //glDisABLE(ALPHA_TEST);
1488 //gluPerspective(90.0,(GLfloat)(grd_curscreen->sc_w*3)/(GLfloat)(grd_curscreen->sc_h*4),1.0,1000000.0);
1489 // ogl_swap_buffers();//platform specific code
1490 // glClear(GL_COLOR_BUFFER_BIT);
1492 void ogl_swap_buffers(void){
1493 ogl_clean_texture_cache();
1494 if (gr_renderstats){
1495 gr_printf(5,GAME_FONT->ft_h*13+3*13,"%i flat %i tex %i sprites %i bitmaps",r_polyc,r_tpolyc,r_bitmapc,r_ubitmapc);
1496 // glmprintf((0,"ogl_end_frame: %i polys, %i tmaps, %i sprites, %i bitmaps, %i bitblts, %i pixels\n",r_polyc,r_tpolyc,r_bitmapc,r_ubitmapc,r_ubitbltc,r_upixelc));//we need to do it here because some things get drawn after end_frame
1499 ogl_swap_buffers_internal();
1500 glClear(GL_COLOR_BUFFER_BIT);
1503 void ogl_init_shared_palette(void)
1505 #ifdef GL_EXT_paletted_texture
1506 if (ogl_shared_palette_ok)
1510 glEnable(GL_SHARED_TEXTURE_PALETTE_EXT);
1511 //glColorTableEXT(GL_SHARED_TEXTURE_PALETTE_EXT, GL_RGB, 256, GL_RGB, GL_UNSIGNED_BYTE, ogl_pal);
1513 for (i = 0; i < 256; i++)
1517 texbuf[i * 4] = 255;
1518 texbuf[i * 4 + 1] = 255;
1519 texbuf[i * 4 + 2] = 255;
1520 texbuf[i * 4 + 3] = 0;
1525 texbuf[i * 4 + 1] = 0;
1526 texbuf[i * 4 + 2] = 0;
1527 texbuf[i * 4 + 3] = 0;
1531 texbuf[i * 4] = gr_current_pal[i * 3] * 4;
1532 texbuf[i * 4 + 1] = gr_current_pal[i * 3 + 1] * 4;
1533 texbuf[i * 4 + 2] = gr_current_pal[i * 3 + 2] * 4;
1534 texbuf[i * 4 + 3] = 255;
1537 glColorTableEXT(GL_SHARED_TEXTURE_PALETTE_EXT, GL_RGBA, 256, GL_RGBA, GL_UNSIGNED_BYTE, texbuf);
1542 int tex_format_supported(int iformat,int format){
1545 if (!ogl_intensity4_ok) return 0; break;
1546 case GL_LUMINANCE4_ALPHA4:
1547 if (!ogl_luminance4_alpha4_ok) return 0; break;
1549 if (!ogl_rgba2_ok) return 0; break;
1551 if (ogl_gettexlevelparam_ok){
1552 GLint internalFormat;
1553 glTexImage2D(GL_PROXY_TEXTURE_2D, 0, iformat, 64, 64, 0,
1554 format, GL_UNSIGNED_BYTE, texbuf);//NULL?
1555 glGetTexLevelParameteriv(GL_PROXY_TEXTURE_2D, 0,
1556 GL_TEXTURE_INTERNAL_FORMAT,
1558 return (internalFormat==iformat);
1563 //little hack to find the largest or equal multiple of 2 for a given number
1567 for (i = 1; i <= 4096; i *= 2)
1572 //GLubyte texbuf[512*512*4];
1573 GLubyte texbuf[OGLTEXBUFSIZE];
1575 void ogl_filltexbuf(unsigned char *data, GLubyte *texp, int truewidth, int width, int height, int dxo, int dyo, int twidth, int theight, int type, int bm_flags, int data_format)
1577 // GLushort *tex=(GLushort *)texp;
1579 if (twidth*theight*4>sizeof(texbuf))//shouldn't happen, descent never uses textures that big.
1580 Error("texture toobig %i %i",twidth,theight);
1583 for (y=0;y<theight;y++){
1584 i=dxo+truewidth*(y+dyo);
1585 for (x=0;x<twidth;x++){
1586 if (x<width && y<height)
1591 for (j = 0; j < data_format; ++j)
1592 (*(texp++)) = data[i * data_format + j];
1599 c = 256; // fill the pad space with transparency (or blackness)
1600 if (c == 254 && (bm_flags & BM_FLAG_SUPER_TRANSPARENT))
1604 case GL_LUMINANCE_ALPHA:
1612 (*(texp++)) = 0; // transparent pixel
1614 case GL_COLOR_INDEX:
1618 Error("ogl_filltexbuf unhandled super-transparent texformat\n");
1622 else if ((c == 255 && (bm_flags & BM_FLAG_TRANSPARENT)) || c == 256)
1628 case GL_LUMINANCE_ALPHA:
1641 (*(texp++))=0;//transparent pixel
1643 case GL_COLOR_INDEX:
1647 Error("ogl_filltexbuf unknown texformat\n");
1652 case GL_LUMINANCE://these could prolly be done to make the intensity based upon the intensity of the resulting color, but its not needed for anything (yet?) so no point. :)
1655 case GL_LUMINANCE_ALPHA:
1660 (*(texp++)) = ogl_pal[c * 3] * 4;
1661 (*(texp++)) = ogl_pal[c * 3 + 1] * 4;
1662 (*(texp++)) = ogl_pal[c * 3 + 2] * 4;
1665 //(*(texp++))=gr_palette[c*3]*4;
1666 //(*(texp++))=gr_palette[c*3+1]*4;
1667 //(*(texp++))=gr_palette[c*3+2]*4;
1668 (*(texp++))=ogl_pal[c*3]*4;
1669 (*(texp++))=ogl_pal[c*3+1]*4;
1670 (*(texp++))=ogl_pal[c*3+2]*4;
1671 (*(texp++))=255;//not transparent
1672 // (*(tex++))=(ogl_pal[c*3]>>1) + ((ogl_pal[c*3+1]>>1)<<5) + ((ogl_pal[c*3+2]>>1)<<10) + (1<<15);
1674 case GL_COLOR_INDEX:
1678 Error("ogl_filltexbuf unknown texformat\n");
1686 int tex_format_verify(ogl_texture *tex){
1687 while (!tex_format_supported(tex->internalformat,tex->format)){
1688 glmprintf((0,"tex format %x not supported",tex->internalformat));
1689 switch (tex->internalformat){
1691 if (ogl_luminance4_alpha4_ok){
1692 tex->internalformat=GL_LUMINANCE4_ALPHA4;
1693 tex->format=GL_LUMINANCE_ALPHA;
1695 }//note how it will fall through here if the statement is false
1696 case GL_LUMINANCE4_ALPHA4:
1698 tex->internalformat=GL_RGBA2;
1699 tex->format=GL_RGBA;
1701 }//note how it will fall through here if the statement is false
1703 #if defined(__APPLE__) && defined(__MACH__)
1704 case GL_RGB8: // Quartz doesn't support RGB only
1706 tex->internalformat = ogl_rgba_internalformat;
1707 tex->format=GL_RGBA;
1710 mprintf((0,"...no tex format to fall back on\n"));
1713 glmprintf((0,"...falling back to %x\n",tex->internalformat));
1717 void tex_set_size1(ogl_texture *tex,int dbits,int bits,int w, int h){
1719 if (tex->tw!=w || tex->th!=h){
1720 u=(tex->w/(float)tex->tw*w) * (tex->h/(float)tex->th*h);
1721 glmprintf((0,"shrunken texture?\n"));
1724 if (bits<=0){//the beta nvidia GLX server. doesn't ever return any bit sizes, so just use some assumptions.
1725 tex->bytes=((float)w*h*dbits)/8.0;
1726 tex->bytesu=((float)u*dbits)/8.0;
1728 tex->bytes=((float)w*h*bits)/8.0;
1729 tex->bytesu=((float)u*bits)/8.0;
1731 glmprintf((0,"tex_set_size1: %ix%i, %ib(%i) %iB\n",w,h,bits,dbits,tex->bytes));
1733 void tex_set_size(ogl_texture *tex){
1736 if (ogl_gettexlevelparam_ok){
1738 glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_WIDTH,&w);
1739 glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_HEIGHT,&h);
1740 glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_LUMINANCE_SIZE,&t);a+=t;
1741 glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_INTENSITY_SIZE,&t);a+=t;
1742 glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_RED_SIZE,&t);a+=t;
1743 glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_GREEN_SIZE,&t);a+=t;
1744 glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_BLUE_SIZE,&t);a+=t;
1745 glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_ALPHA_SIZE,&t);a+=t;
1746 #ifdef GL_EXT_paletted_texture
1747 if (ogl_paletted_texture_ok)
1749 glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INDEX_SIZE_EXT, &t);
1757 switch (tex->format){
1761 case GL_LUMINANCE_ALPHA:
1768 case GL_COLOR_INDEX:
1772 Error("tex_set_size unknown texformat\n");
1775 tex_set_size1(tex,bi,a,w,h);
1777 //loads a palettized bitmap into a ogl RGBA texture.
1778 //Sizes and pads dimensions to multiples of 2 if necessary.
1779 //In theory this could be a problem for repeating textures, but all real
1780 //textures (not sprites, etc) in descent are 64x64, so we are ok.
1781 //stores OpenGL textured id in *texid and u/v values required to get only the real data in *u/*v
1782 void ogl_loadtexture(unsigned char *data, int dxo, int dyo, ogl_texture *tex, int bm_flags, int data_format)
1784 //void ogl_loadtexture(unsigned char * data, int width, int height,int dxo,int dyo, int *texid,float *u,float *v,char domipmap,float prio){
1785 // int internalformat=GL_RGBA;
1786 // int format=GL_RGBA;
1788 tex->tw=pow2ize(tex->w);tex->th=pow2ize(tex->h);//calculate smallest texture size that can accomodate us (must be multiples of 2)
1789 // tex->tw=tex->w;tex->th=tex->h;//feeling lucky?
1791 if(gr_badtexture>0) return;
1793 if (tex_format_verify(tex))
1796 //calculate u/v values that would make the resulting texture correctly sized
1797 tex->u=(float)tex->w/(float)tex->tw;
1798 tex->v=(float)tex->h/(float)tex->th;
1800 #ifdef GL_EXT_paletted_texture
1801 if (ogl_shared_palette_ok && data_format == 0 && (tex->format == GL_RGBA || tex->format == GL_RGB) &&
1802 !(tex->wantmip && GL_needmipmaps) // gluBuild2DMipmaps doesn't support paletted textures.. this could be worked around be generating our own mipmaps, but thats too much trouble at the moment.
1805 // descent makes palette entries 254 and 255 both do double duty, depending upon the setting of BM_FLAG_SUPER_TRANSPARENT and BM_FLAG_TRANSPARENT.
1806 // So if the texture doesn't have BM_FLAG_TRANSPARENT set, yet uses index 255, we cannot use the palette for it since that color would be incorrect. (this case is much less common than transparent textures, hence why we don't exclude those instead.)
1807 // We don't handle super transparent textures with ogl yet, so we don't bother checking that here.
1808 int usesthetransparentindexcolor = 0, usesthesupertransparentindexcolor = 0;
1810 if (!(bm_flags & BM_FLAG_SUPER_TRANSPARENT))
1814 for (i = 0; i < tex->w * tex->h; ++i)
1816 usesthesupertransparentindexcolor += 1;
1818 if (!(bm_flags & BM_FLAG_TRANSPARENT))
1822 for (i=0; i < tex->w * tex->h; ++i)
1824 usesthetransparentindexcolor += 1;
1826 if (!usesthetransparentindexcolor && !usesthesupertransparentindexcolor)
1828 tex->internalformat = GL_COLOR_INDEX8_EXT;
1829 tex->format = GL_COLOR_INDEX;
1832 // printf("bm data=%p w=%i h=%i transparent:%i supertrans:%i\n", data, tex->w, tex->h, usesthetransparentindexcolor, usesthesupertransparentindexcolor);
1836 // if (width!=twidth || height!=theight)
1837 // glmprintf((0,"sizing %ix%i texture up to %ix%i\n",width,height,twidth,theight));
1838 ogl_filltexbuf(data, texbuf, tex->lw, tex->w, tex->h, dxo, dyo, tex->tw, tex->th, tex->format, bm_flags, data_format);
1840 // Generate OpenGL texture IDs.
1841 glGenTextures(1, &tex->handle);
1844 glPrioritizeTextures(1,&tex->handle,&tex->prio);
1846 // Give our data to OpenGL.
1848 OGL_BINDTEXTURE(tex->handle);
1850 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
1852 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_texmagfilt);
1853 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_texminfilt);
1854 if (ogl_ext_texture_filter_anisotropic_ok && GL_texanisofilt)
1855 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, GL_texanisofilt);
1859 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1860 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1862 // domipmap=0;//mipmaps aren't used in GL_NEAREST anyway, and making the mipmaps is pretty slow
1863 //however, if texturing mode becomes an ingame option, they would need to be made regardless, so it could switch to them later. OTOH, texturing mode could just be made a command line arg.
1865 if (tex->wantmip && GL_needmipmaps)
1866 gluBuild2DMipmaps( GL_TEXTURE_2D, tex->internalformat, tex->tw,
1867 tex->th, tex->format, GL_UNSIGNED_BYTE, texbuf);
1869 glTexImage2D(GL_TEXTURE_2D, 0, tex->internalformat,
1870 tex->tw, tex->th, 0, tex->format, // RGBA textures.
1871 GL_UNSIGNED_BYTE, // imageData is a GLubyte pointer.
1877 glmprintf((0,"ogl_loadtexture(%p,%i,%i,%ix%i,%p):%i u=%f v=%f b=%i bu=%i (%i)\n",data,tex->tw,tex->th,dxo,dyo,tex,tex->handle,tex->u,tex->v,tex->bytes,tex->bytesu,r_texcount));
1881 unsigned char decodebuf[1024*1024];
1883 void ogl_loadbmtexture_f(grs_bitmap *bm, int flags)
1890 while (bm->bm_parent)
1892 if (bm->gltexture && bm->gltexture->handle > 0)
1896 if ((bitmapname = piggy_game_bitmap_name(bm)))
1901 sprintf(filename, "textures/%s.png", bitmapname);
1902 if (read_png(filename, &pdata))
1904 printf("%s: %ux%ux%i p=%i(%i) c=%i a=%i chans=%i\n", filename, pdata.width, pdata.height, pdata.depth, pdata.paletted, pdata.num_palette, pdata.color, pdata.alpha, pdata.channels);
1905 if (pdata.depth == 8 && pdata.color)
1907 if (bm->gltexture == NULL)
1908 ogl_init_texture(bm->gltexture = ogl_get_free_texture(), pdata.width, pdata.height, flags | ((pdata.alpha || bm->bm_flags & BM_FLAG_TRANSPARENT) ? OGL_FLAG_ALPHA : 0));
1909 ogl_loadtexture(pdata.data, 0, 0, bm->gltexture, bm->bm_flags, pdata.paletted ? 0 : pdata.channels);
1912 free(pdata.palette);
1917 printf("%s: unsupported texture format: must be rgb, rgba, or paletted, and depth 8\n", filename);
1920 free(pdata.palette);
1925 if (bm->gltexture == NULL){
1926 ogl_init_texture(bm->gltexture = ogl_get_free_texture(), bm->bm_w, bm->bm_h, flags | ((bm->bm_flags & (BM_FLAG_TRANSPARENT | BM_FLAG_SUPER_TRANSPARENT))? OGL_FLAG_ALPHA : 0));
1929 if (bm->gltexture->handle>0)
1931 if (bm->gltexture->w==0){
1932 bm->gltexture->lw=bm->bm_w;
1933 bm->gltexture->w=bm->bm_w;
1934 bm->gltexture->h=bm->bm_h;
1937 if (bm->bm_flags & BM_FLAG_RLE){
1938 unsigned char * dbits;
1939 unsigned char * sbits;
1943 if (bm->bm_flags & BM_FLAG_RLE_BIG)
1946 sbits = &bm->bm_data[4 + (bm->bm_h * data_offset)];
1949 for (i=0; i < bm->bm_h; i++ ) {
1950 gr_rle_decode(sbits,dbits);
1951 if ( bm->bm_flags & BM_FLAG_RLE_BIG )
1952 sbits += (int)INTEL_SHORT(*((short *)&(bm->bm_data[4+(i*data_offset)])));
1954 sbits += (int)bm->bm_data[4+i];
1959 ogl_loadtexture(buf, 0, 0, bm->gltexture, bm->bm_flags, 0);
1962 void ogl_loadbmtexture(grs_bitmap *bm)
1964 ogl_loadbmtexture_f(bm, OGL_FLAG_MIPMAP);
1967 void ogl_freetexture(ogl_texture *gltexture)
1969 if (gltexture->handle>0) {
1971 glmprintf((0,"ogl_freetexture(%p):%i (last rend %is) (%i left)\n",gltexture,gltexture->handle,(GameTime-gltexture->lastrend)/f1_0,r_texcount));
1972 glDeleteTextures( 1, &gltexture->handle );
1973 // gltexture->handle=0;
1974 ogl_reset_texture(gltexture);
1977 void ogl_freebmtexture(grs_bitmap *bm){
1979 ogl_freetexture(bm->gltexture);
1982 // glmprintf((0,"ogl_freebmtexture(%p,%p):%i (%i left)\n",bm->bm_data,&bm->gltexture,bm->gltexture,r_texcount));
1983 // glDeleteTextures( 1, &bm->gltexture );
1984 // bm->gltexture=-1;