3 * Graphics support functions for OpenGL.
18 #if defined(__APPLE__) && defined(__MACH__)
19 #include <OpenGL/gl.h>
20 #include <OpenGL/glu.h>
31 #include "../../3d/globvars.h"
53 //change to 1 for lots of spew.
55 #define glmprintf(a) mprintf(a)
64 #if defined(_WIN32) || (defined(__APPLE__) && defined(__MACH__)) || defined(__sun__) || defined(macintosh)
65 #define cosf(a) cos(a)
66 #define sinf(a) sin(a)
69 unsigned char *ogl_pal=gr_palette;
71 int GL_texmagfilt=GL_NEAREST;
72 int GL_texminfilt=GL_NEAREST;
73 float GL_texanisofilt = 0;
76 int last_width=-1,last_height=-1;
77 int GL_TEXTURE_2D_enabled=-1;
78 int GL_texclamp_enabled=-1;
80 extern int gr_badtexture;
81 int r_texcount = 0, r_cachedtexcount = 0;
82 int ogl_alttexmerge=1;//merge textures by just printing the seperate textures?
83 int ogl_rgba_internalformat = GL_RGBA8;
84 int ogl_rgb_internalformat = GL_RGB8;
85 int ogl_intensity4_ok=1;
86 int ogl_luminance4_alpha4_ok=1;
88 int ogl_readpixels_ok=1;
89 int ogl_gettexlevelparam_ok=1;
90 #ifdef GL_ARB_multitexture
91 int ogl_arb_multitexture_ok=0;
93 #ifdef GL_SGIS_multitexture
94 int ogl_sgis_multitexture_ok=0;
96 int ogl_nv_texture_env_combine4_ok = 0;
97 #ifdef GL_NV_register_combiners
98 int ogl_nv_register_combiners_ok = 0;
100 int ogl_ext_texture_filter_anisotropic_ok = 0;
101 #ifdef GL_EXT_paletted_texture
102 int ogl_shared_palette_ok = 0;
103 int ogl_paletted_texture_ok = 0;
107 int cross_lh[2]={0,0};
108 int primary_lh[3]={0,0,0};
109 int secondary_lh[5]={0,0,0,0,0};
112 #define OGL_BINDTEXTURE(a) if(gr_badtexture>0) glBindTexture(GL_TEXTURE_2D, 0);\
113 else if(a!=lastbound) {glBindTexture(GL_TEXTURE_2D, a);lastbound=a;}*/
114 #define OGL_BINDTEXTURE(a) if(gr_badtexture>0) glBindTexture(GL_TEXTURE_2D, 0);\
115 else glBindTexture(GL_TEXTURE_2D, a);
118 ogl_texture ogl_texture_list[OGL_TEXTURE_LIST_SIZE];
119 int ogl_texture_list_cur;
121 /* some function prototypes */
123 //#define OGLTEXBUFSIZE (1024*1024*4)
124 #define OGLTEXBUFSIZE (2048*2048*4)
125 extern GLubyte texbuf[OGLTEXBUFSIZE];
126 //void ogl_filltexbuf(unsigned char *data,GLubyte *texp,int width,int height,int twidth,int theight);
127 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);
128 void ogl_loadbmtexture(grs_bitmap *bm);
129 //void ogl_loadtexture(unsigned char * data, int width, int height,int dxo,intdyo , int *texid,float *u,float *v,char domipmap,float prio);
130 void ogl_loadtexture(unsigned char *data, int dxo, int dyo, ogl_texture *tex, int bm_flags, int data_format);
131 void ogl_freetexture(ogl_texture *gltexture);
132 void ogl_do_palfx(void);
134 void ogl_init_texture_stats(ogl_texture* t){
135 t->prio=0.3;//default prio
139 void ogl_init_texture(ogl_texture* t, int w, int h, int flags)
142 if (flags & OGL_FLAG_NOCOLOR)
144 // use GL_INTENSITY instead of GL_RGB
145 if (flags & OGL_FLAG_ALPHA)
147 if (ogl_intensity4_ok)
149 t->internalformat = GL_INTENSITY4;
150 t->format = GL_LUMINANCE;
152 else if (ogl_luminance4_alpha4_ok)
154 t->internalformat = GL_LUMINANCE4_ALPHA4;
155 t->format = GL_LUMINANCE_ALPHA;
157 else if (ogl_rgba2_ok)
159 t->internalformat = GL_RGBA2;
164 t->internalformat = ogl_rgba_internalformat;
170 // there are certainly smaller formats we could use here, but nothing needs it ATM.
171 t->internalformat = ogl_rgb_internalformat;
177 if (flags & OGL_FLAG_ALPHA)
179 t->internalformat = ogl_rgba_internalformat;
184 t->internalformat = ogl_rgb_internalformat;
188 t->wrapstate[0] = -1;
189 t->wrapstate[1] = -1;
192 t->wantmip = flags & OGL_FLAG_MIPMAP;
193 ogl_init_texture_stats(t);
196 void ogl_reset_texture(ogl_texture* t)
198 ogl_init_texture(t, 0, 0, 0);
201 void ogl_reset_texture_stats_internal(void){
203 for (i=0;i<OGL_TEXTURE_LIST_SIZE;i++)
204 if (ogl_texture_list[i].handle>0){
205 ogl_init_texture_stats(&ogl_texture_list[i]);
208 void ogl_init_texture_list_internal(void){
210 ogl_texture_list_cur=0;
211 for (i=0;i<OGL_TEXTURE_LIST_SIZE;i++)
212 ogl_reset_texture(&ogl_texture_list[i]);
214 void ogl_smash_texture_list_internal(void){
217 memset(cross_lh,0,sizeof(cross_lh));
218 memset(primary_lh,0,sizeof(primary_lh));
219 memset(secondary_lh,0,sizeof(secondary_lh));
220 for (i=0;i<OGL_TEXTURE_LIST_SIZE;i++){
221 if (ogl_texture_list[i].handle>0){
222 glDeleteTextures( 1, &ogl_texture_list[i].handle );
223 ogl_texture_list[i].handle=0;
225 ogl_texture_list[i].wrapstate[0] = -1;
226 ogl_texture_list[i].wrapstate[1] = -1;
229 void ogl_vivify_texture_list_internal(void){
233 for (i=0;i<OGL_TEXTURE_LIST_SIZE;i++){
234 t=&ogl_texture_list[i];
235 if (t->w>0){//erk, realised this can't be done since we'd need the texture bm_data too. hmmm.
236 ogl_loadbmtexture(t);
241 ogl_texture* ogl_get_free_texture(void){
243 for (i=0;i<OGL_TEXTURE_LIST_SIZE;i++){
244 if (ogl_texture_list[ogl_texture_list_cur].handle<=0 && ogl_texture_list[ogl_texture_list_cur].w==0)
245 return &ogl_texture_list[ogl_texture_list_cur];
246 if (++ogl_texture_list_cur>=OGL_TEXTURE_LIST_SIZE)
247 ogl_texture_list_cur=0;
249 Error("OGL: texture list full!\n");
252 int ogl_texture_stats(void){
253 int used = 0, usedother = 0, usedidx = 0, usedrgb = 0, usedrgba = 0;
254 int databytes = 0, truebytes = 0, datatexel = 0, truetexel = 0, i;
255 int prio0=0,prio1=0,prio2=0,prio3=0,prioh=0;
258 for (i=0;i<OGL_TEXTURE_LIST_SIZE;i++){
259 t=&ogl_texture_list[i];
262 datatexel+=t->w*t->h;
263 truetexel+=t->tw*t->th;
264 databytes+=t->bytesu;
266 if (t->prio<0.299)prio0++;
267 else if (t->prio<0.399)prio1++;
268 else if (t->prio<0.499)prio2++;
269 else if (t->prio<0.599)prio3++;
271 if (t->format == GL_RGBA)
273 else if (t->format == GL_RGB)
275 else if (t->format == GL_COLOR_INDEX)
285 GLint idx, r, g, b, a, dbl, depth;
286 int res, colorsize, depthsize;
288 res = SWIDTH * SHEIGHT;
289 glGetIntegerv(GL_INDEX_BITS, &idx);
290 glGetIntegerv(GL_RED_BITS, &r);
291 glGetIntegerv(GL_GREEN_BITS, &g);
292 glGetIntegerv(GL_BLUE_BITS, &b);
293 glGetIntegerv(GL_ALPHA_BITS, &a);
294 glGetIntegerv(GL_DOUBLEBUFFER, &dbl);
296 glGetIntegerv(GL_DEPTH_BITS, &depth);
297 colorsize = (idx * res * dbl) / 8;
298 depthsize = res * depth / 8;
299 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);
300 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);
301 gr_printf(5, GAME_FONT->ft_h * 16 + 3 * 16, "total=%iK", (colorsize + depthsize + truebytes) / 1024);
303 // 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));
306 int ogl_mem_target=-1;
307 void ogl_clean_texture_cache(void){
312 if (ogl_mem_target<0){
318 bytes=ogl_texture_stats();
319 while (bytes>ogl_mem_target){
320 for (i=0;i<OGL_TEXTURE_LIST_SIZE;i++){
321 t=&ogl_texture_list[i];
323 if (t->lastrend+f1_0*time<GameTime){
326 if (bytes<ogl_mem_target)
332 Error("not enough mem?");
337 void ogl_bindbmtex(grs_bitmap *bm){
338 if (bm->gltexture==NULL || bm->gltexture->handle<=0)
339 ogl_loadbmtexture(bm);
340 OGL_BINDTEXTURE(bm->gltexture->handle);
341 bm->gltexture->lastrend=GameTime;
342 bm->gltexture->numrend++;
343 //// if (bm->gltexture->numrend==80 || bm->gltexture->numrend==4000 || bm->gltexture->numrend==80000){
344 // if (bm->gltexture->numrend==100){
345 // bm->gltexture->prio+=0.1;
346 //// glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_PRIORITY,bm->gltexture->prio);
347 // glPrioritizeTextures(1,&bm->gltexture->handle,&bm->gltexture->prio);
350 //gltexture MUST be bound first
351 void ogl_texwrap(ogl_texture *gltexture,int state)
353 if (gltexture->wrapstate[active_texture_unit] != state || gltexture->numrend < 1)
355 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, state);
356 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, state);
357 gltexture->wrapstate[active_texture_unit] = state;
361 //crude texture precaching
362 //handles: powerups, walls, weapons, polymodels, etc.
363 //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.
364 //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
367 void ogl_cache_polymodel_textures(int model_num)
374 po = &Polygon_models[model_num];
375 for (i=0;i<po->n_textures;i++) {
376 // texture_list_index[i] = ObjBitmaps[ObjBitmapPtrs[po->first_texture+i]];
377 ogl_loadbmtexture(&GameBitmaps[ObjBitmaps[ObjBitmapPtrs[po->first_texture+i]].index]);
380 void ogl_cache_vclip_textures(vclip *vc){
382 for (i=0;i<vc->num_frames;i++){
383 PIGGY_PAGE_IN(vc->frames[i]);
384 ogl_loadbmtexture(&GameBitmaps[vc->frames[i].index]);
388 void ogl_cache_vclipn_textures(int i)
390 if (i >= 0 && i < VCLIP_MAXNUM)
391 ogl_cache_vclip_textures(&Vclip[i]);
394 void ogl_cache_weapon_textures(int weapon_type)
400 w = &Weapon_info[weapon_type];
401 ogl_cache_vclipn_textures(w->flash_vclip);
402 ogl_cache_vclipn_textures(w->robot_hit_vclip);
403 ogl_cache_vclipn_textures(w->wall_hit_vclip);
404 if (w->render_type==WEAPON_RENDER_VCLIP)
405 ogl_cache_vclipn_textures(w->weapon_vclip);
406 else if (w->render_type == WEAPON_RENDER_POLYMODEL)
408 ogl_cache_polymodel_textures(w->model_num);
409 ogl_cache_polymodel_textures(w->model_num_inner);
413 void ogl_cache_level_textures(void)
422 ogl_reset_texture_stats_internal();//loading a new lev should reset textures
424 for (i=0,ec=Effects;i<Num_effects;i++,ec++) {
425 ogl_cache_vclipn_textures(Effects[i].dest_vclip);
426 if ((Effects[i].changing_wall_texture == -1) && (Effects[i].changing_object_texture==-1) )
428 if (ec->vc.num_frames>max_efx)
429 max_efx=ec->vc.num_frames;
431 glmprintf((0,"max_efx:%i\n",max_efx));
432 for (ef=0;ef<max_efx;ef++){
433 for (i=0,ec=Effects;i<Num_effects;i++,ec++) {
434 if ((Effects[i].changing_wall_texture == -1) && (Effects[i].changing_object_texture==-1) )
436 // if (ec->vc.num_frames>max_efx)
437 // max_efx=ec->vc.num_frames;
440 do_special_effects();
442 for (seg=0;seg<Num_segments;seg++){
443 for (side=0;side<MAX_SIDES_PER_SEGMENT;side++){
444 sidep=&Segments[seg].sides[side];
445 tmap1=sidep->tmap_num;
446 tmap2=sidep->tmap_num2;
447 if (tmap1<0 || tmap1>=NumTextures){
448 glmprintf((0,"ogl_cache_level_textures %i %i %i %i\n",seg,side,tmap1,NumTextures));
452 PIGGY_PAGE_IN(Textures[tmap1]);
453 bm = &GameBitmaps[Textures[tmap1].index];
455 PIGGY_PAGE_IN(Textures[tmap2&0x3FFF]);
456 bm2 = &GameBitmaps[Textures[tmap2&0x3FFF].index];
457 if (ogl_alttexmerge == 0 || (!OGL_SUPER_TRANSPARENT_OK && (bm2->bm_flags & BM_FLAG_SUPER_TRANSPARENT)))
458 bm = texmerge_get_cached_bitmap( tmap1, tmap2 );
460 ogl_loadbmtexture(bm2);
462 // 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));
464 ogl_loadbmtexture(bm);
467 glmprintf((0,"finished ef:%i\n",ef));
469 reset_special_effects();
470 init_special_effects();
474 // always have lasers, concs, flares. Always shows player appearance, and at least concs are always available to disappear.
475 ogl_cache_weapon_textures(Primary_weapon_to_weapon_info[LASER_INDEX]);
476 ogl_cache_weapon_textures(Secondary_weapon_to_weapon_info[CONCUSSION_INDEX]);
477 ogl_cache_weapon_textures(FLARE_ID);
478 ogl_cache_vclipn_textures(VCLIP_PLAYER_APPEARANCE);
479 ogl_cache_vclipn_textures(VCLIP_POWERUP_DISAPPEARANCE);
480 ogl_cache_polymodel_textures(Player_ship->model_num);
481 ogl_cache_vclipn_textures(Player_ship->expl_vclip_num);
483 for (i=0;i<Highest_object_index;i++){
484 if(Objects[i].render_type==RT_POWERUP){
485 ogl_cache_vclipn_textures(Objects[i].rtype.vclip_info.vclip_num);
486 switch (Objects[i].id){
488 ogl_cache_weapon_textures(Primary_weapon_to_weapon_info[LASER_INDEX]);
492 case POW_VULCAN_WEAPON:
493 ogl_cache_weapon_textures(Primary_weapon_to_weapon_info[VULCAN_INDEX]);
495 case POW_SPREADFIRE_WEAPON:
496 ogl_cache_weapon_textures(Primary_weapon_to_weapon_info[SPREADFIRE_INDEX]);
498 case POW_PLASMA_WEAPON:
499 ogl_cache_weapon_textures(Primary_weapon_to_weapon_info[PLASMA_INDEX]);
501 case POW_FUSION_WEAPON:
502 ogl_cache_weapon_textures(Primary_weapon_to_weapon_info[FUSION_INDEX]);
504 /* case POW_MISSILE_1:
506 ogl_cache_weapon_textures(Secondary_weapon_to_weapon_info[CONCUSSION_INDEX]);
508 case POW_PROXIMITY_WEAPON:
509 ogl_cache_weapon_textures(Secondary_weapon_to_weapon_info[PROXIMITY_INDEX]);
511 case POW_HOMING_AMMO_1:
512 case POW_HOMING_AMMO_4:
513 ogl_cache_weapon_textures(Primary_weapon_to_weapon_info[HOMING_INDEX]);
515 case POW_SMARTBOMB_WEAPON:
516 ogl_cache_weapon_textures(Secondary_weapon_to_weapon_info[SMART_INDEX]);
518 case POW_MEGA_WEAPON:
519 ogl_cache_weapon_textures(Secondary_weapon_to_weapon_info[MEGA_INDEX]);
523 else if(Objects[i].render_type==RT_POLYOBJ){
524 //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);
525 if (Objects[i].type == OBJ_ROBOT)
527 ogl_cache_vclipn_textures(Robot_info[Objects[i].id].exp1_vclip_num);
528 ogl_cache_vclipn_textures(Robot_info[Objects[i].id].exp2_vclip_num);
529 ogl_cache_weapon_textures(Robot_info[Objects[i].id].weapon_type);
531 if (Objects[i].rtype.pobj_info.tmap_override != -1)
532 ogl_loadbmtexture(&GameBitmaps[Textures[Objects[i].rtype.pobj_info.tmap_override].index]);
534 ogl_cache_polymodel_textures(Objects[i].rtype.pobj_info.model_num);
538 glmprintf((0,"finished caching\n"));
539 r_cachedtexcount = r_texcount;
542 int r_polyc,r_tpolyc,r_bitmapc,r_ubitmapc,r_ubitbltc,r_upixelc;
543 #define f2glf(x) (f2fl(x))
545 bool g3_draw_line(g3s_point *p0,g3s_point *p1)
548 c=grd_curcanv->cv_color;
549 OGL_DISABLE(TEXTURE_2D);
550 glColor3f(PAL2Tr(c),PAL2Tg(c),PAL2Tb(c));
552 glVertex3f(f2glf(p0->p3_vec.x),f2glf(p0->p3_vec.y),-f2glf(p0->p3_vec.z));
553 glVertex3f(f2glf(p1->p3_vec.x),f2glf(p1->p3_vec.y),-f2glf(p1->p3_vec.z));
557 void ogl_drawcircle2(int nsides,int type,float xsc,float xo,float ysc,float yo){
561 for (i=0; i<nsides; i++) {
562 ang = 2.0*M_PI*i/nsides;
563 glVertex2f(cosf(ang)*xsc+xo,sinf(ang)*ysc+yo);
567 void ogl_drawcircle(int nsides,int type){
571 for (i=0; i<nsides; i++) {
572 ang = 2.0*M_PI*i/nsides;
573 glVertex2f(cosf(ang),sinf(ang));
577 int circle_list_init(int nsides,int type,int mode) {
578 int hand=glGenLists(1);
579 glNewList(hand, mode);
580 /* draw a unit radius circle in xy plane centered on origin */
581 ogl_drawcircle(nsides,type);
585 float bright_g[4]={ 32.0/256, 252.0/256, 32.0/256};
586 float dark_g[4]={ 32.0/256, 148.0/256, 32.0/256};
587 float darker_g[4]={ 32.0/256, 128.0/256, 32.0/256};
588 void ogl_draw_reticle(int cross,int primary,int secondary){
589 float scale=(float)Canvas_height/(float)grd_curscreen->sc_h;
591 // glTranslatef(0.5,0.5,0);
592 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);
593 glScalef(scale/320.0,scale/200.0,scale);//the positions are based upon the standard reticle at 320x200 res.
595 OGL_DISABLE(TEXTURE_2D);
597 if (!cross_lh[cross]){
598 cross_lh[cross]=glGenLists(1);
599 glNewList(cross_lh[cross], GL_COMPILE_AND_EXECUTE);
602 glColor3fv(darker_g);
603 glVertex2f(-4.0,4.0);
605 glColor3fv(bright_g);
608 glVertex2f(-2.0,2.0);
612 glVertex2f(-3.0,-2.0);
614 glColor3fv(bright_g);
615 glVertex2f(-2.0,-1.0);
618 glColor3fv(darker_g);
621 glColor3fv(bright_g);
628 glVertex2f(3.0,-2.0);
630 glColor3fv(bright_g);
631 glVertex2f(2.0,-1.0);
636 glCallList(cross_lh[cross]);
638 // if (Canvas_height>200)
639 // glLineWidth(Canvas_height/(float)200);
640 if (!primary_lh[primary]){
641 primary_lh[primary]=glGenLists(1);
642 glNewList(primary_lh[primary], GL_COMPILE_AND_EXECUTE);
647 glVertex2f(-14.0,-8.0);
648 glVertex2f(-8.0,-5.0);
650 glVertex2f(14.0,-8.0);
651 glVertex2f(8.0,-5.0);
656 glColor3fv(bright_g);
658 ogl_drawcircle2(6,GL_POLYGON,1.5,-7.0,1.5,-5.0);
660 ogl_drawcircle2(6,GL_POLYGON,1.5,7.0,1.5,-5.0);
664 glColor3fv(bright_g);
666 ogl_drawcircle2(4,GL_POLYGON,1.0,-14.0,1.0,-8.0);
668 ogl_drawcircle2(4,GL_POLYGON,1.0,14.0,1.0,-8.0);
672 glCallList(primary_lh[primary]);
673 // if (Canvas_height>200)
676 if (!secondary_lh[secondary]){
677 secondary_lh[secondary]=glGenLists(1);
678 glNewList(secondary_lh[secondary], GL_COMPILE_AND_EXECUTE);
682 glColor3fv(darker_g);
684 glColor3fv(bright_g);
685 ogl_drawcircle2(8,GL_LINE_LOOP,2.0,-10.0,2.0,-1.0);
688 glColor3fv(darker_g);
690 glColor3fv(bright_g);
691 ogl_drawcircle2(8,GL_LINE_LOOP,2.0,10.0,2.0,-1.0);
693 //bottom/middle secondary
695 glColor3fv(darker_g);
697 glColor3fv(bright_g);
698 ogl_drawcircle2(8,GL_LINE_LOOP,2.0,0.0,2.0,-7.0);
702 glCallList(secondary_lh[secondary]);
706 int g3_draw_sphere(g3s_point *pnt,fix rad){
708 c=grd_curcanv->cv_color;
709 OGL_DISABLE(TEXTURE_2D);
710 // glPointSize(f2glf(rad));
711 glColor3f(CPAL2Tr(c),CPAL2Tg(c),CPAL2Tb(c));
712 // glBegin(GL_POINTS);
713 // glVertex3f(f2glf(pnt->p3_vec.x),f2glf(pnt->p3_vec.y),-f2glf(pnt->p3_vec.z));
716 glTranslatef(f2glf(pnt->p3_vec.x),f2glf(pnt->p3_vec.y),-f2glf(pnt->p3_vec.z));
717 glScalef(f2glf(rad),f2glf(rad),f2glf(rad));
718 if (!sphereh) sphereh=circle_list_init(20,GL_POLYGON,GL_COMPILE_AND_EXECUTE);
719 else glCallList(sphereh);
724 int gr_ucircle(fix xc1, fix yc1, fix r1)
727 c=grd_curcanv->cv_color;
728 OGL_DISABLE(TEXTURE_2D);
729 glColor3f(CPAL2Tr(c),CPAL2Tg(c),CPAL2Tb(c));
732 (f2fl(xc1) + grd_curcanv->cv_bitmap.bm_x + 0.5) / (float)last_width,
733 1.0 - (f2fl(yc1) + grd_curcanv->cv_bitmap.bm_y + 0.5) / (float)last_height,0);
734 glScalef(f2fl(r1) / last_width, f2fl(r1) / last_height, 1.0);
735 ogl_drawcircle(10 + 2 * (int)(M_PI * f2fl(r1) / 19), GL_LINE_LOOP);
739 int gr_circle(fix xc1,fix yc1,fix r1){
740 return gr_ucircle(xc1,yc1,r1);
743 bool g3_draw_poly(int nv,g3s_point **pointlist)
747 c=grd_curcanv->cv_color;
748 // 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);
749 OGL_DISABLE(TEXTURE_2D);
750 if (Gr_scanline_darkening_level >= GR_FADE_LEVELS)
751 glColor3f(PAL2Tr(c), PAL2Tg(c), PAL2Tb(c));
753 glColor4f(PAL2Tr(c), PAL2Tg(c), PAL2Tb(c), 1.0 - (float)Gr_scanline_darkening_level / ((float)GR_FADE_LEVELS - 1.0));
754 glBegin(GL_TRIANGLE_FAN);
756 // glVertex3f(f2glf(pointlist[c]->p3_vec.x),f2glf(pointlist[c]->p3_vec.y),f2glf(pointlist[c]->p3_vec.z));
757 glVertex3f(f2glf(pointlist[c]->p3_vec.x),f2glf(pointlist[c]->p3_vec.y),-f2glf(pointlist[c]->p3_vec.z));
763 void gr_upoly_tmap(int nverts, int *vert ){
764 mprintf((0,"gr_upoly_tmap: unhandled\n"));//should never get called
766 void draw_tmap_flat(grs_bitmap *bm,int nv,g3s_point **vertlist){
767 mprintf((0,"draw_tmap_flat: unhandled\n"));//should never get called
769 extern void (*tmap_drawer_ptr)(grs_bitmap *bm,int nv,g3s_point **vertlist);
770 bool g3_draw_tmap(int nv,g3s_point **pointlist,g3s_uvl *uvl_list,grs_bitmap *bm)
774 if (tmap_drawer_ptr==draw_tmap_flat){
775 /* fix average_light=0;
778 average_light += uvl_list[i].l;*/
779 OGL_DISABLE(TEXTURE_2D);
780 // glmprintf((0,"Gr_scanline_darkening_level=%i %f\n",Gr_scanline_darkening_level,Gr_scanline_darkening_level/(float)NUM_LIGHTING_LEVELS));
781 glColor4f(0,0,0,1.0-(Gr_scanline_darkening_level/(float)NUM_LIGHTING_LEVELS));
782 //glColor4f(0,0,0,f2fl(average_light/nv));
783 glBegin(GL_TRIANGLE_FAN);
785 // glColor4f(0,0,0,f2fl(uvl_list[c].l));
786 // glTexCoord2f(f2glf(uvl_list[c].u),f2glf(uvl_list[c].v));
787 glVertex3f(f2glf(pointlist[c]->p3_vec.x),f2glf(pointlist[c]->p3_vec.y),-f2glf(pointlist[c]->p3_vec.z));
790 }else if (tmap_drawer_ptr==draw_tmap){
792 /* if (bm->bm_w !=64||bm->bm_h!=64)
793 printf("g3_draw_tmap w %i h %i\n",bm->bm_w,bm->bm_h);*/
794 OGL_ENABLE(TEXTURE_2D);
796 ogl_texwrap(bm->gltexture,GL_REPEAT);
797 glBegin(GL_TRIANGLE_FAN);
799 if (bm->bm_flags&BM_FLAG_NO_LIGHTING){
802 //l=f2fl(uvl_list[c].l)+gr_palette_gamma/63.0;
803 l=f2fl(uvl_list[c].l);
806 glTexCoord2f(f2glf(uvl_list[c].u),f2glf(uvl_list[c].v));
807 //glVertex3f(f2glf(pointlist[c]->p3_vec.x),f2glf(pointlist[c]->p3_vec.y),f2glf(pointlist[c]->p3_vec.z));
808 glVertex3f(f2glf(pointlist[c]->p3_vec.x),f2glf(pointlist[c]->p3_vec.y),-f2glf(pointlist[c]->p3_vec.z));
812 mprintf((0,"g3_draw_tmap: unhandled tmap_drawer %p\n",tmap_drawer_ptr));
817 int active_texture_unit = 0;
819 void ogl_setActiveTexture(int t)
821 if (ogl_arb_multitexture_ok)
823 #ifdef GL_ARB_multitexture
825 glActiveTextureARB(GL_TEXTURE0_ARB);
827 glActiveTextureARB(GL_TEXTURE1_ARB);
830 else if (ogl_sgis_multitexture_ok)
832 #ifdef GL_SGIS_multitexture
834 glSelectTextureSGIS(GL_TEXTURE0_SGIS);
836 glSelectTextureSGIS(GL_TEXTURE1_SGIS);
839 active_texture_unit = t;
842 void ogl_MultiTexCoord2f(int t, float u, float v)
844 if (ogl_arb_multitexture_ok)
846 #ifdef GL_ARB_multitexture
848 glMultiTexCoord2fARB(GL_TEXTURE0_ARB, u, v);
850 glMultiTexCoord2fARB(GL_TEXTURE1_ARB, u, v);
853 else if (ogl_sgis_multitexture_ok)
855 #ifdef GL_SGIS_multitexture
857 glMultiTexCoord2fSGIS(GL_TEXTURE0_SGIS, u, v);
859 glMultiTexCoord2fSGIS(GL_TEXTURE1_SGIS, u, v);
864 bool g3_draw_tmap_2(int nv, g3s_point **pointlist, g3s_uvl *uvl_list, grs_bitmap *bmbot, grs_bitmap *bm, int orient)
866 #if ((defined(GL_NV_register_combiners) || defined(GL_NV_texture_env_combine4)) && (defined(GL_ARB_multitexture) || defined(GL_SGIS_multitexture)))
867 if ((/*ogl_nv_register_combiners_ok ||*/ ogl_nv_texture_env_combine4_ok) && (ogl_arb_multitexture_ok || ogl_sgis_multitexture_ok))
872 if (tmap_drawer_ptr != draw_tmap)
877 //ogl_setActiveTexture(0);
878 OGL_ENABLE(TEXTURE_2D);
879 ogl_bindbmtex(bmbot);
880 ogl_texwrap(bmbot->gltexture, GL_REPEAT);
881 // GL_MODULATE is fine for texture 0
883 ogl_setActiveTexture(1);
884 glEnable(GL_TEXTURE_2D);
886 ogl_texwrap(bm->gltexture,GL_REPEAT);
888 #ifdef GL_NV_register_combiners
889 if (ogl_nv_register_combiners_ok)
891 glEnable(GL_REGISTER_COMBINERS_NV);
892 glCombinerParameteriNV(GL_NUM_GENERAL_COMBINERS_NV, 1);
893 // spare0 = tex0 * (1-alpha1) + tex1 * alpha1
894 glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_A_NV, GL_TEXTURE0_ARB, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
895 glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_B_NV, GL_TEXTURE1_ARB, GL_UNSIGNED_INVERT_NV, GL_ALPHA);
896 glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_C_NV, GL_TEXTURE1_ARB, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
897 glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_D_NV, GL_TEXTURE1_ARB, GL_UNSIGNED_IDENTITY_NV, GL_ALPHA);
899 GL_COMBINER0_NV, //GLenum stage
900 GL_RGB, //GLenum portion,
901 GL_DISCARD_NV, //GLenum abOutput,
902 GL_DISCARD_NV, //GLenum cdOutput,
903 GL_SPARE0_NV, //GLenum sumOutput,
904 GL_NONE, //GLenum scale,
905 GL_NONE, //GLenum bias,
906 GL_FALSE, //GLboolean abDotProduct,
907 GL_FALSE, //GLboolean cdDotProduct,
908 GL_FALSE //GLboolean muxSum
910 // out = spare0 * color
911 // ( out = AB + (1-A)C + D )
912 glFinalCombinerInputNV(GL_VARIABLE_A_NV, GL_SPARE0_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
913 glFinalCombinerInputNV(GL_VARIABLE_B_NV, GL_PRIMARY_COLOR_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
914 glFinalCombinerInputNV(GL_VARIABLE_C_NV, GL_ZERO, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
915 glFinalCombinerInputNV(GL_VARIABLE_D_NV, GL_ZERO, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
917 if (bm->bm_flags & BM_FLAG_SUPER_TRANSPARENT)
919 // out = alpha0*(1-tex1) + alpha1
920 glCombinerInputNV(GL_COMBINER0_NV, GL_ALPHA, GL_VARIABLE_A_NV, GL_TEXTURE0_ARB, GL_UNSIGNED_IDENTITY_NV, GL_ALPHA);
921 glCombinerInputNV(GL_COMBINER0_NV, GL_ALPHA, GL_VARIABLE_B_NV, GL_TEXTURE1_ARB, GL_UNSIGNED_INVERT_NV, GL_BLUE);
922 glCombinerInputNV(GL_COMBINER0_NV, GL_ALPHA, GL_VARIABLE_C_NV, GL_TEXTURE1_ARB, GL_UNSIGNED_IDENTITY_NV, GL_ALPHA);
923 glCombinerInputNV(GL_COMBINER0_NV, GL_ALPHA, GL_VARIABLE_D_NV, GL_ZERO, GL_UNSIGNED_INVERT_NV, GL_ALPHA);
927 // out = alpha0 + alpha1
928 glCombinerInputNV(GL_COMBINER0_NV, GL_ALPHA, GL_VARIABLE_A_NV, GL_TEXTURE0_ARB, GL_UNSIGNED_IDENTITY_NV, GL_ALPHA);
929 glCombinerInputNV(GL_COMBINER0_NV, GL_ALPHA, GL_VARIABLE_B_NV, GL_ZERO, GL_UNSIGNED_INVERT_NV, GL_ALPHA);
930 glCombinerInputNV(GL_COMBINER0_NV, GL_ALPHA, GL_VARIABLE_C_NV, GL_TEXTURE1_ARB, GL_UNSIGNED_IDENTITY_NV, GL_ALPHA);
931 glCombinerInputNV(GL_COMBINER0_NV, GL_ALPHA, GL_VARIABLE_D_NV, GL_ZERO, GL_UNSIGNED_INVERT_NV, GL_ALPHA);
934 GL_COMBINER0_NV, //GLenum stage
935 GL_ALPHA, //GLenum portion,
936 GL_DISCARD_NV, //GLenum abOutput,
937 GL_DISCARD_NV, //GLenum cdOutput,
938 GL_SPARE0_NV, //GLenum sumOutput,
939 GL_NONE, //GLenum scale,
940 GL_NONE, //GLenum bias,
941 GL_FALSE, //GLboolean abDotProduct,
942 GL_FALSE, //GLboolean cdDotProduct,
943 GL_FALSE //GLboolean muxSum
945 glFinalCombinerInputNV(GL_VARIABLE_G_NV, GL_SPARE0_NV, GL_UNSIGNED_IDENTITY_NV, GL_ALPHA);
950 //http://oss.sgi.com/projects/ogl-sample/registry/NV/texture_env_combine4.txt
951 //only GL_NV_texture_env_combine4 lets us do what we need:
952 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE4_NV);
954 //multiply top texture by color(vertex lighting) and add bottom texture(where alpha says to)
955 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_ADD);
957 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE);
958 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PRIMARY_COLOR_EXT);
959 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_EXT, GL_TEXTURE);
960 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE3_RGB_NV, GL_PREVIOUS_EXT);
962 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, GL_SRC_COLOR);
963 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_EXT, GL_SRC_COLOR);
964 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_EXT, GL_ONE_MINUS_SRC_ALPHA);
965 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND3_RGB_NV, GL_SRC_COLOR);
967 //add up alpha channels
968 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_ADD);
970 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_TEXTURE);
971 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_EXT, GL_ZERO);
972 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA_EXT, GL_PREVIOUS_EXT);
973 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE3_ALPHA_NV, GL_ZERO);
975 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT, GL_SRC_ALPHA);
976 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_EXT, GL_ONE_MINUS_SRC_ALPHA);
977 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA_EXT, GL_SRC_ALPHA);
978 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND3_ALPHA_NV, GL_ONE_MINUS_SRC_ALPHA);
981 // GL_DECAL works sorta ok but the top texture is fullbright.
982 //glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
984 // GL_ARB_texture_env_combine comes close, but doesn't quite make it.
985 //glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
987 //// this gives effect like GL_DECAL:
988 //glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_INTERPOLATE);
989 //glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
990 //glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB);
991 //glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_TEXTURE);
994 // this properly shades the top texture, but the bottom texture doesn't get through.
995 //glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
996 //glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PRIMARY_COLOR_ARB);
997 //glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE);
1001 //glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_ADD);
1002 //glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
1003 //glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_PREVIOUS_ARB);
1005 glBegin(GL_TRIANGLE_FAN);
1009 u1=1.0-f2glf(uvl_list[c].v);
1010 v1=f2glf(uvl_list[c].u);
1013 u1=1.0-f2glf(uvl_list[c].u);
1014 v1=1.0-f2glf(uvl_list[c].v);
1017 u1=f2glf(uvl_list[c].v);
1018 v1=1.0-f2glf(uvl_list[c].u);
1021 u1=f2glf(uvl_list[c].u);
1022 v1=f2glf(uvl_list[c].v);
1025 if (bm->bm_flags&BM_FLAG_NO_LIGHTING){
1028 l=f2fl(uvl_list[c].l);
1031 ogl_MultiTexCoord2f(0, f2glf(uvl_list[c].u), f2glf(uvl_list[c].v));
1032 ogl_MultiTexCoord2f(1, u1, v1);
1033 //glVertex3f(f2glf(pointlist[c]->p3_vec.x),f2glf(pointlist[c]->p3_vec.y),f2glf(pointlist[c]->p3_vec.z));
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));
1038 //ogl_setActiveTexture(1); // still the active texture
1039 #ifdef GL_NV_register_combiners
1040 if (ogl_nv_register_combiners_ok)
1042 glDisable(GL_REGISTER_COMBINERS_NV);
1047 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
1049 glDisable(GL_TEXTURE_2D);
1050 ogl_setActiveTexture(0);
1058 g3_draw_tmap(nv,pointlist,uvl_list,bmbot);//draw the bottom texture first.. could be optimized with multitexturing..
1061 /* if (bm->bm_w !=64||bm->bm_h!=64)
1062 printf("g3_draw_tmap w %i h %i\n",bm->bm_w,bm->bm_h);*/
1063 OGL_ENABLE(TEXTURE_2D);
1065 ogl_texwrap(bm->gltexture,GL_REPEAT);
1066 glBegin(GL_TRIANGLE_FAN);
1070 u1=1.0-f2glf(uvl_list[c].v);
1071 v1=f2glf(uvl_list[c].u);
1074 u1=1.0-f2glf(uvl_list[c].u);
1075 v1=1.0-f2glf(uvl_list[c].v);
1078 u1=f2glf(uvl_list[c].v);
1079 v1=1.0-f2glf(uvl_list[c].u);
1082 u1=f2glf(uvl_list[c].u);
1083 v1=f2glf(uvl_list[c].v);
1086 if (bm->bm_flags&BM_FLAG_NO_LIGHTING){
1089 //l=f2fl(uvl_list[c].l)+gr_palette_gamma/63.0;
1090 l=f2fl(uvl_list[c].l);
1093 glTexCoord2f(u1,v1);
1094 //glVertex3f(f2glf(pointlist[c]->p3_vec.x),f2glf(pointlist[c]->p3_vec.y),f2glf(pointlist[c]->p3_vec.z));
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));
1103 bool g3_draw_bitmap(vms_vector *pos,fix width,fix height,grs_bitmap *bm, int orientation)
1106 vms_vector pv,v1;//,v2;
1110 // printf("g3_draw_bitmap: %f,%f,%f - ",f2glf(pos->x),f2glf(pos->y),-f2glf(pos->z));
1111 // printf("(%f,%f,%f) ",f2glf(View_position.x),f2glf(View_position.y),-f2glf(View_position.z));
1113 OGL_ENABLE(TEXTURE_2D);
1115 ogl_texwrap(bm->gltexture,GL_CLAMP);
1118 glColor3f(1.0,1.0,1.0);
1119 width = fixmul(width,Matrix_scale.x);
1120 height = fixmul(height,Matrix_scale.y);
1122 // g3_rotate_point(&p[i],pos);
1123 vm_vec_sub(&v1,pos,&View_position);
1124 vm_vec_rotate(&pv,&v1,&View_matrix);
1125 // printf(" %f,%f,%f->",f2glf(pv.x),f2glf(pv.y),-f2glf(pv.z));
1128 glTexCoord2f(0.0, 0.0);
1133 glTexCoord2f(bm->gltexture->u, 0.0);
1138 glTexCoord2f(bm->gltexture->u, bm->gltexture->v);
1143 glTexCoord2f(0.0, bm->gltexture->v);
1148 // vm_vec_rotate(&v2,&v1,&View_matrix);
1149 // vm_vec_sub(&v1,&v2,&pv);
1150 //vm_vec_sub(&v1,&pv,&v2);
1151 // vm_vec_sub(&v2,&pv,&v1);
1152 glVertex3f(f2glf(pv.x),f2glf(pv.y),-f2glf(pv.z));
1153 // printf("%f,%f,%f ",f2glf(v1.x),f2glf(v1.y),-f2glf(v1.z));
1161 bool ogl_ubitmapm_c(int x, int y,grs_bitmap *bm,int c)
1163 GLfloat xo,yo,xf,yf;
1164 GLfloat u1,u2,v1,v2;
1166 x+=grd_curcanv->cv_bitmap.bm_x;
1167 y+=grd_curcanv->cv_bitmap.bm_y;
1168 xo=x/(float)last_width;
1169 xf=(bm->bm_w+x)/(float)last_width;
1170 yo=1.0-y/(float)last_height;
1171 yf=1.0-(bm->bm_h+y)/(float)last_height;
1173 // printf("g3_draw_bitmap: %f,%f,%f - ",f2glf(pos->x),f2glf(pos->y),-f2glf(pos->z));
1174 // printf("(%f,%f,%f) ",f2glf(View_position.x),f2glf(View_position.y),-f2glf(View_position.z));
1176 /* glEnABLE(ALPHA_TEST);
1177 glAlphaFunc(GL_GREATER,0.0);*/
1179 OGL_ENABLE(TEXTURE_2D);
1181 ogl_texwrap(bm->gltexture,GL_CLAMP);
1185 if (bm->bm_w==bm->gltexture->w)
1186 u2=bm->gltexture->u;
1188 u2=(bm->bm_w+bm->bm_x)/(float)bm->gltexture->tw;
1190 u1=bm->bm_x/(float)bm->gltexture->tw;
1191 u2=(bm->bm_w+bm->bm_x)/(float)bm->gltexture->tw;
1195 if (bm->bm_h==bm->gltexture->h)
1196 v2=bm->gltexture->v;
1198 v2=(bm->bm_h+bm->bm_y)/(float)bm->gltexture->th;
1200 v1=bm->bm_y/(float)bm->gltexture->th;
1201 v2=(bm->bm_h+bm->bm_y)/(float)bm->gltexture->th;
1206 glColor3f(1.0,1.0,1.0);
1208 glColor3f(CPAL2Tr(c),CPAL2Tg(c),CPAL2Tb(c));
1209 glTexCoord2f(u1, v1); glVertex2f(xo, yo);
1210 glTexCoord2f(u2, v1); glVertex2f(xf, yo);
1211 glTexCoord2f(u2, v2); glVertex2f(xf, yf);
1212 glTexCoord2f(u1, v2); glVertex2f(xo, yf);
1214 // glDisABLE(ALPHA_TEST);
1218 bool ogl_ubitmapm(int x, int y,grs_bitmap *bm){
1219 return ogl_ubitmapm_c(x,y,bm,-1);
1220 // return ogl_ubitblt(bm->bm_w,bm->bm_h,x,y,0,0,bm,NULL);
1223 //also upsidedown, currently.
1224 bool ogl_ubitblt(int w,int h,int dx,int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest)
1226 GLfloat xo,yo;//,xs,ys;
1227 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));
1232 xo=dx/(float)last_width;
1233 // xo=dx/(float)grd_curscreen->sc_w;
1234 // xs=w/(float)last_width;
1235 //yo=1.0-dy/(float)last_height;
1236 yo=1.0-(dy+h)/(float)last_height;
1237 // ys=h/(float)last_height;
1239 // OGL_ENABLE(TEXTURE_2D);
1241 OGL_DISABLE(TEXTURE_2D);
1242 glRasterPos2f(xo,yo);
1243 ogl_filltexbuf(src->bm_data,texbuf,src->bm_w,w,h,sx,sy,w,h,GL_RGBA);
1244 glDrawPixels(w,h,GL_RGBA,GL_UNSIGNED_BYTE,texbuf);
1250 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)
1252 GLfloat xo,yo,xs,ys;
1253 GLfloat u1,v1;//,u2,v2;
1255 // unsigned char *oldpal;
1258 ogl_init_texture(&tex, sw, sh, OGL_FLAG_ALPHA);
1260 tex.lw=src->bm_rowsize;
1262 /* if (w==src->bm_w && sx==0){
1265 u1=sx/(float)src->bm_w*src->glu;
1266 u2=w/(float)src->bm_w*src->glu+u1;
1268 if (h==src->bm_h && sy==0){
1271 v1=sy/(float)src->bm_h*src->glv;
1272 v2=h/(float)src->bm_h*src->glv+v1;
1278 xo=dx/(float)last_width;
1279 xs=dw/(float)last_width;
1280 yo=1.0-dy/(float)last_height;
1281 ys=dh/(float)last_height;
1283 OGL_ENABLE(TEXTURE_2D);
1286 ogl_pal=gr_current_pal;
1287 ogl_loadtexture(src->bm_data, sx, sy, &tex, src->bm_flags, 0);
1290 OGL_BINDTEXTURE(tex.handle);
1292 ogl_texwrap(&tex,GL_CLAMP);
1295 glColor3f(1.0,1.0,1.0);
1296 glTexCoord2f(u1, v1); glVertex2f(xo, yo);
1297 glTexCoord2f(tex.u, v1); glVertex2f(xo+xs, yo);
1298 glTexCoord2f(tex.u, tex.v); glVertex2f(xo+xs, yo-ys);
1299 glTexCoord2f(u1, tex.v); glVertex2f(xo, yo-ys);
1301 ogl_freetexture(&tex);
1304 bool ogl_ubitblt(int w,int h,int dx,int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest){
1305 return ogl_ubitblt_i(w,h,dx,dy,w,h,sx,sy,src,dest);
1308 bool ogl_ubitblt_tolinear(int w,int h,int dx,int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest){
1310 unsigned char *d,*s;
1314 w1=grd_curscreen->sc_w;h1=grd_curscreen->sc_h;
1315 if (w1*h1*3>OGLTEXBUFSIZE)
1316 Error("ogl_ubitblt_tolinear: screen res larger than OGLTEXBUFSIZE\n");
1318 if (ogl_readpixels_ok>0){
1319 OGL_DISABLE(TEXTURE_2D);
1320 glReadBuffer(GL_FRONT);
1321 glReadPixels(0,0,w1,h1,GL_RGB,GL_UNSIGNED_BYTE,texbuf);
1322 // glReadPixels(sx,grd_curscreen->sc_h-(sy+h),w,h,GL_RGB,GL_UNSIGNED_BYTE,texbuf);
1323 // glReadPixels(sx,sy,w+sx,h+sy,GL_RGB,GL_UNSIGNED_BYTE,texbuf);
1325 memset(texbuf,0,w1*h1*3);
1329 d=dest->bm_data+dx+(dy+i)*dest->bm_rowsize;
1330 s=texbuf+((h1-(i+sy+1))*w1+sx)*3;
1332 *d=gr_find_closest_color(s[0]/4,s[1]/4,s[2]/4);
1339 unsigned char *d,*s,*e;
1340 if (w*h*3>OGLTEXBUFSIZE)
1341 Error("ogl_ubitblt_tolinear: size larger than OGLTEXBUFSIZE\n");
1344 #if 1//also seems to cause a mess. need to look into it a bit more..
1345 if (ogl_readpixels_ok>0){
1346 OGL_DISABLE(TEXTURE_2D);
1347 glReadBuffer(GL_FRONT);
1348 // glReadPixels(0,0,w,h,GL_RGB,GL_UNSIGNED_BYTE,texbuf);
1349 glReadPixels(sx,grd_curscreen->sc_h-(sy+h),w,h,GL_RGB,GL_UNSIGNED_BYTE,texbuf);
1352 memset(texbuf,0,w*h*3);
1353 // d=dest->bm_data+dx+(dy+i)*dest->bm_rowsize;
1354 d=dest->bm_data+dx+dy*dest->bm_rowsize;
1356 s=texbuf+w*(h-(i+1))*3;
1358 if (s<texbuf){Error("blah1\n");}
1359 if (d<dest->bm_data){Error("blah3\n");}
1360 // d=dest->bm_data+(i*dest->bm_rowsize);
1364 if (s>texbuf+w*h*3-3){Error("blah2\n");}
1365 if (d>dest->bm_data+dest->bm_rowsize*(h+dy)+dx ){Error("blah4\n");}
1366 *d=gr_find_closest_color(s[0]/4,s[1]/4,s[2]/4);
1372 d+=dest->bm_rowsize;
1374 glmprintf((0,"c=%i w*h=%i\n",c,w*h));
1379 bool ogl_ubitblt_copy(int w,int h,int dx,int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest){
1380 #if 0 //just seems to cause a mess.
1381 GLfloat xo,yo;//,xs,ys;
1386 // xo=dx/(float)last_width;
1387 xo=dx/(float)grd_curscreen->sc_w;
1388 // yo=1.0-(dy+h)/(float)last_height;
1389 yo=1.0-(dy+h)/(float)grd_curscreen->sc_h;
1392 OGL_DISABLE(TEXTURE_2D);
1393 glReadBuffer(GL_FRONT);
1394 glRasterPos2f(xo,yo);
1395 // glReadPixels(0,0,w,h,GL_RGB,GL_UNSIGNED_BYTE,texbuf);
1396 glCopyPixels(sx,grd_curscreen->sc_h-(sy+h),w,h,GL_COLOR);
1402 grs_canvas *offscreen_save_canv = NULL, *offscreen_canv = NULL;
1404 void ogl_start_offscreen_render(int x, int y, int w, int h)
1407 Error("ogl_start_offscreen_render: offscreen_canv!=NULL");
1408 offscreen_save_canv = grd_curcanv;
1409 offscreen_canv = gr_create_sub_canvas(grd_curcanv, x, y, w, h);
1410 gr_set_current_canvas(offscreen_canv);
1411 glDrawBuffer(GL_BACK);
1413 void ogl_end_offscreen_render(void)
1417 if (!offscreen_canv)
1418 Error("ogl_end_offscreen_render: no offscreen_canv");
1420 glDrawBuffer(GL_FRONT);
1421 glReadBuffer(GL_BACK);
1422 OGL_DISABLE(TEXTURE_2D);
1424 y = last_height - offscreen_canv->cv_bitmap.bm_y - offscreen_canv->cv_bitmap.bm_h;
1425 glRasterPos2f(offscreen_canv->cv_bitmap.bm_x/(float)last_width, y/(float)last_height);
1426 glCopyPixels(offscreen_canv->cv_bitmap.bm_x, y,
1427 offscreen_canv->cv_bitmap.bm_w,
1428 offscreen_canv->cv_bitmap.bm_h, GL_COLOR);
1430 gr_free_sub_canvas(offscreen_canv);
1431 gr_set_current_canvas(offscreen_save_canv);
1432 offscreen_canv=NULL;
1435 void ogl_start_frame(void){
1436 r_polyc=0;r_tpolyc=0;r_bitmapc=0;r_ubitmapc=0;r_ubitbltc=0;r_upixelc=0;
1437 // gl_badtexture=500;
1439 OGL_VIEWPORT(grd_curcanv->cv_bitmap.bm_x,grd_curcanv->cv_bitmap.bm_y,Canvas_width,Canvas_height);
1440 glClearColor(0.0, 0.0, 0.0, 0.0);
1441 // glEnable(GL_ALPHA_TEST);
1442 // glAlphaFunc(GL_GREATER,0.01);
1443 glShadeModel(GL_SMOOTH);
1444 glMatrixMode(GL_PROJECTION);
1445 glLoadIdentity();//clear matrix
1446 //gluPerspective(90.0,(GLfloat)(grd_curscreen->sc_w*3)/(GLfloat)(grd_curscreen->sc_h*4),1.0,1000000.0);
1447 //gluPerspective(90.0,(GLfloat)(grd_curscreen->sc_w*3)/(GLfloat)(grd_curscreen->sc_h*4),0.01,1000000.0);
1448 gluPerspective(90.0,1.0,0.01,1000000.0);
1449 //gluPerspective(90.0,(GLfloat)(Canvas_width*3)/(GLfloat)(Canvas_height*4),0.01,1000000.0);
1450 // gluPerspective(75.0,(GLfloat)Canvas_width/(GLfloat)Canvas_height,1.0,1000000.0);
1451 glMatrixMode(GL_MODELVIEW);
1452 glLoadIdentity();//clear matrix
1454 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1455 // glDisABLE(DITHER);
1456 // glScalef(1.0,1.0,-1.0);
1457 // glScalef(1.0,1.0,-1.0);
1460 // glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
1461 // OGL_TEXENV(GL_TEXTURE_ENV_MODE,GL_MODULATE);
1462 // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_texmagfilt);
1463 // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_texminfilt);
1464 // OGL_TEXPARAM(GL_TEXTURE_MAG_FILTER,GL_texmagfilt);
1465 // OGL_TEXPARAM(GL_TEXTURE_MIN_FILTER,GL_texminfilt);
1466 // glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1467 // glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1470 void merge_textures_stats(void);
1472 void ogl_end_frame(void){
1473 // OGL_VIEWPORT(grd_curcanv->cv_bitmap.bm_x,grd_curcanv->cv_bitmap.bm_y,);
1474 OGL_VIEWPORT(0,0,grd_curscreen->sc_w,grd_curscreen->sc_h);
1476 // merge_textures_stats();
1477 // ogl_texture_stats();
1479 // glViewport(0,0,grd_curscreen->sc_w,grd_curscreen->sc_h);
1480 glMatrixMode(GL_PROJECTION);
1481 glLoadIdentity();//clear matrix
1482 glOrtho(0.0, 1.0, 0.0, 1.0, -1.0, 1.0);
1483 glMatrixMode(GL_MODELVIEW);
1484 glLoadIdentity();//clear matrix
1485 // glDisABLE(BLEND);
1486 //glDisABLE(ALPHA_TEST);
1487 //gluPerspective(90.0,(GLfloat)(grd_curscreen->sc_w*3)/(GLfloat)(grd_curscreen->sc_h*4),1.0,1000000.0);
1488 // ogl_swap_buffers();//platform specific code
1489 // glClear(GL_COLOR_BUFFER_BIT);
1491 void ogl_swap_buffers(void){
1492 ogl_clean_texture_cache();
1493 if (gr_renderstats){
1494 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);
1495 // 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
1498 ogl_swap_buffers_internal();
1499 glClear(GL_COLOR_BUFFER_BIT);
1502 void ogl_init_shared_palette(void)
1504 #ifdef GL_EXT_paletted_texture
1505 if (ogl_shared_palette_ok)
1509 glEnable(GL_SHARED_TEXTURE_PALETTE_EXT);
1510 //glColorTableEXT(GL_SHARED_TEXTURE_PALETTE_EXT, GL_RGB, 256, GL_RGB, GL_UNSIGNED_BYTE, ogl_pal);
1512 for (i = 0; i < 256; i++)
1516 texbuf[i * 4] = 255;
1517 texbuf[i * 4 + 1] = 255;
1518 texbuf[i * 4 + 2] = 255;
1519 texbuf[i * 4 + 3] = 0;
1524 texbuf[i * 4 + 1] = 0;
1525 texbuf[i * 4 + 2] = 0;
1526 texbuf[i * 4 + 3] = 0;
1530 texbuf[i * 4] = gr_current_pal[i * 3] * 4;
1531 texbuf[i * 4 + 1] = gr_current_pal[i * 3 + 1] * 4;
1532 texbuf[i * 4 + 2] = gr_current_pal[i * 3 + 2] * 4;
1533 texbuf[i * 4 + 3] = 255;
1536 glColorTableEXT(GL_SHARED_TEXTURE_PALETTE_EXT, GL_RGBA, 256, GL_RGBA, GL_UNSIGNED_BYTE, texbuf);
1541 int tex_format_supported(int iformat,int format){
1544 if (!ogl_intensity4_ok) return 0; break;
1545 case GL_LUMINANCE4_ALPHA4:
1546 if (!ogl_luminance4_alpha4_ok) return 0; break;
1548 if (!ogl_rgba2_ok) return 0; break;
1550 if (ogl_gettexlevelparam_ok){
1551 GLint internalFormat;
1552 glTexImage2D(GL_PROXY_TEXTURE_2D, 0, iformat, 64, 64, 0,
1553 format, GL_UNSIGNED_BYTE, texbuf);//NULL?
1554 glGetTexLevelParameteriv(GL_PROXY_TEXTURE_2D, 0,
1555 GL_TEXTURE_INTERNAL_FORMAT,
1557 return (internalFormat==iformat);
1562 //little hack to find the largest or equal multiple of 2 for a given number
1566 for (i = 1; i <= 4096; i *= 2)
1571 //GLubyte texbuf[512*512*4];
1572 GLubyte texbuf[OGLTEXBUFSIZE];
1574 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)
1576 // GLushort *tex=(GLushort *)texp;
1578 if (twidth*theight*4>sizeof(texbuf))//shouldn't happen, descent never uses textures that big.
1579 Error("texture toobig %i %i",twidth,theight);
1582 for (y=0;y<theight;y++){
1583 i=dxo+truewidth*(y+dyo);
1584 for (x=0;x<twidth;x++){
1585 if (x<width && y<height)
1590 for (j = 0; j < data_format; ++j)
1591 (*(texp++)) = data[i * data_format + j];
1598 c = 256; // fill the pad space with transparency (or blackness)
1599 if (c == 254 && (bm_flags & BM_FLAG_SUPER_TRANSPARENT))
1603 case GL_LUMINANCE_ALPHA:
1611 (*(texp++)) = 0; // transparent pixel
1613 case GL_COLOR_INDEX:
1617 Error("ogl_filltexbuf unhandled super-transparent texformat\n");
1621 else if ((c == 255 && (bm_flags & BM_FLAG_TRANSPARENT)) || c == 256)
1627 case GL_LUMINANCE_ALPHA:
1640 (*(texp++))=0;//transparent pixel
1642 case GL_COLOR_INDEX:
1646 Error("ogl_filltexbuf unknown texformat\n");
1651 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. :)
1654 case GL_LUMINANCE_ALPHA:
1659 (*(texp++)) = ogl_pal[c * 3] * 4;
1660 (*(texp++)) = ogl_pal[c * 3 + 1] * 4;
1661 (*(texp++)) = ogl_pal[c * 3 + 2] * 4;
1664 //(*(texp++))=gr_palette[c*3]*4;
1665 //(*(texp++))=gr_palette[c*3+1]*4;
1666 //(*(texp++))=gr_palette[c*3+2]*4;
1667 (*(texp++))=ogl_pal[c*3]*4;
1668 (*(texp++))=ogl_pal[c*3+1]*4;
1669 (*(texp++))=ogl_pal[c*3+2]*4;
1670 (*(texp++))=255;//not transparent
1671 // (*(tex++))=(ogl_pal[c*3]>>1) + ((ogl_pal[c*3+1]>>1)<<5) + ((ogl_pal[c*3+2]>>1)<<10) + (1<<15);
1673 case GL_COLOR_INDEX:
1677 Error("ogl_filltexbuf unknown texformat\n");
1685 int tex_format_verify(ogl_texture *tex){
1686 while (!tex_format_supported(tex->internalformat,tex->format)){
1687 glmprintf((0,"tex format %x not supported",tex->internalformat));
1688 switch (tex->internalformat){
1690 if (ogl_luminance4_alpha4_ok){
1691 tex->internalformat=GL_LUMINANCE4_ALPHA4;
1692 tex->format=GL_LUMINANCE_ALPHA;
1694 }//note how it will fall through here if the statement is false
1695 case GL_LUMINANCE4_ALPHA4:
1697 tex->internalformat=GL_RGBA2;
1698 tex->format=GL_RGBA;
1700 }//note how it will fall through here if the statement is false
1702 #if defined(__APPLE__) && defined(__MACH__)
1703 case GL_RGB8: // Quartz doesn't support RGB only
1705 tex->internalformat = ogl_rgba_internalformat;
1706 tex->format=GL_RGBA;
1709 mprintf((0,"...no tex format to fall back on\n"));
1712 glmprintf((0,"...falling back to %x\n",tex->internalformat));
1716 void tex_set_size1(ogl_texture *tex,int dbits,int bits,int w, int h){
1718 if (tex->tw!=w || tex->th!=h){
1719 u=(tex->w/(float)tex->tw*w) * (tex->h/(float)tex->th*h);
1720 glmprintf((0,"shrunken texture?\n"));
1723 if (bits<=0){//the beta nvidia GLX server. doesn't ever return any bit sizes, so just use some assumptions.
1724 tex->bytes=((float)w*h*dbits)/8.0;
1725 tex->bytesu=((float)u*dbits)/8.0;
1727 tex->bytes=((float)w*h*bits)/8.0;
1728 tex->bytesu=((float)u*bits)/8.0;
1730 glmprintf((0,"tex_set_size1: %ix%i, %ib(%i) %iB\n",w,h,bits,dbits,tex->bytes));
1732 void tex_set_size(ogl_texture *tex){
1735 if (ogl_gettexlevelparam_ok){
1737 glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_WIDTH,&w);
1738 glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_HEIGHT,&h);
1739 glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_LUMINANCE_SIZE,&t);a+=t;
1740 glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_INTENSITY_SIZE,&t);a+=t;
1741 glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_RED_SIZE,&t);a+=t;
1742 glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_GREEN_SIZE,&t);a+=t;
1743 glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_BLUE_SIZE,&t);a+=t;
1744 glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_ALPHA_SIZE,&t);a+=t;
1745 #ifdef GL_EXT_paletted_texture
1746 if (ogl_paletted_texture_ok)
1748 glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INDEX_SIZE_EXT, &t);
1756 switch (tex->format){
1760 case GL_LUMINANCE_ALPHA:
1767 case GL_COLOR_INDEX:
1771 Error("tex_set_size unknown texformat\n");
1774 tex_set_size1(tex,bi,a,w,h);
1776 //loads a palettized bitmap into a ogl RGBA texture.
1777 //Sizes and pads dimensions to multiples of 2 if necessary.
1778 //In theory this could be a problem for repeating textures, but all real
1779 //textures (not sprites, etc) in descent are 64x64, so we are ok.
1780 //stores OpenGL textured id in *texid and u/v values required to get only the real data in *u/*v
1781 void ogl_loadtexture(unsigned char *data, int dxo, int dyo, ogl_texture *tex, int bm_flags, int data_format)
1783 //void ogl_loadtexture(unsigned char * data, int width, int height,int dxo,int dyo, int *texid,float *u,float *v,char domipmap,float prio){
1784 // int internalformat=GL_RGBA;
1785 // int format=GL_RGBA;
1787 tex->tw=pow2ize(tex->w);tex->th=pow2ize(tex->h);//calculate smallest texture size that can accomodate us (must be multiples of 2)
1788 // tex->tw=tex->w;tex->th=tex->h;//feeling lucky?
1790 if(gr_badtexture>0) return;
1792 if (tex_format_verify(tex))
1795 //calculate u/v values that would make the resulting texture correctly sized
1796 tex->u=(float)tex->w/(float)tex->tw;
1797 tex->v=(float)tex->h/(float)tex->th;
1799 #ifdef GL_EXT_paletted_texture
1800 if (ogl_shared_palette_ok && data_format == 0 && (tex->format == GL_RGBA || tex->format == GL_RGB) &&
1801 !(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.
1804 // descent makes palette entries 254 and 255 both do double duty, depending upon the setting of BM_FLAG_SUPER_TRANSPARENT and BM_FLAG_TRANSPARENT.
1805 // 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.)
1806 // We don't handle super transparent textures with ogl yet, so we don't bother checking that here.
1807 int usesthetransparentindexcolor = 0, usesthesupertransparentindexcolor = 0;
1809 if (!(bm_flags & BM_FLAG_SUPER_TRANSPARENT))
1813 for (i = 0; i < tex->w * tex->h; ++i)
1815 usesthesupertransparentindexcolor += 1;
1817 if (!(bm_flags & BM_FLAG_TRANSPARENT))
1821 for (i=0; i < tex->w * tex->h; ++i)
1823 usesthetransparentindexcolor += 1;
1825 if (!usesthetransparentindexcolor && !usesthesupertransparentindexcolor)
1827 tex->internalformat = GL_COLOR_INDEX8_EXT;
1828 tex->format = GL_COLOR_INDEX;
1831 // printf("bm data=%p w=%i h=%i transparent:%i supertrans:%i\n", data, tex->w, tex->h, usesthetransparentindexcolor, usesthesupertransparentindexcolor);
1835 // if (width!=twidth || height!=theight)
1836 // glmprintf((0,"sizing %ix%i texture up to %ix%i\n",width,height,twidth,theight));
1837 ogl_filltexbuf(data, texbuf, tex->lw, tex->w, tex->h, dxo, dyo, tex->tw, tex->th, tex->format, bm_flags, data_format);
1839 // Generate OpenGL texture IDs.
1840 glGenTextures(1, &tex->handle);
1843 glPrioritizeTextures(1,&tex->handle,&tex->prio);
1845 // Give our data to OpenGL.
1847 OGL_BINDTEXTURE(tex->handle);
1849 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
1851 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_texmagfilt);
1852 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_texminfilt);
1853 if (ogl_ext_texture_filter_anisotropic_ok && GL_texanisofilt)
1854 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, GL_texanisofilt);
1858 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1859 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1861 // domipmap=0;//mipmaps aren't used in GL_NEAREST anyway, and making the mipmaps is pretty slow
1862 //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.
1864 if (tex->wantmip && GL_needmipmaps)
1865 gluBuild2DMipmaps( GL_TEXTURE_2D, tex->internalformat, tex->tw,
1866 tex->th, tex->format, GL_UNSIGNED_BYTE, texbuf);
1868 glTexImage2D(GL_TEXTURE_2D, 0, tex->internalformat,
1869 tex->tw, tex->th, 0, tex->format, // RGBA textures.
1870 GL_UNSIGNED_BYTE, // imageData is a GLubyte pointer.
1876 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));
1880 unsigned char decodebuf[1024*1024];
1882 void ogl_loadbmtexture_f(grs_bitmap *bm, int flags)
1889 while (bm->bm_parent)
1891 if (bm->gltexture && bm->gltexture->handle > 0)
1895 if ((bitmapname = piggy_game_bitmap_name(bm)))
1900 sprintf(filename, "textures/%s.png", bitmapname);
1901 if (read_png(filename, &pdata))
1903 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);
1904 if (pdata.depth == 8 && pdata.color)
1906 if (bm->gltexture == NULL)
1907 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));
1908 ogl_loadtexture(pdata.data, 0, 0, bm->gltexture, bm->bm_flags, pdata.paletted ? 0 : pdata.channels);
1911 free(pdata.palette);
1916 printf("%s: unsupported texture format: must be rgb, rgba, or paletted, and depth 8\n", filename);
1919 free(pdata.palette);
1924 if (bm->gltexture == NULL){
1925 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));
1928 if (bm->gltexture->handle>0)
1930 if (bm->gltexture->w==0){
1931 bm->gltexture->lw=bm->bm_w;
1932 bm->gltexture->w=bm->bm_w;
1933 bm->gltexture->h=bm->bm_h;
1936 if (bm->bm_flags & BM_FLAG_RLE){
1937 unsigned char * dbits;
1938 unsigned char * sbits;
1942 if (bm->bm_flags & BM_FLAG_RLE_BIG)
1945 sbits = &bm->bm_data[4 + (bm->bm_h * data_offset)];
1948 for (i=0; i < bm->bm_h; i++ ) {
1949 gr_rle_decode(sbits,dbits);
1950 if ( bm->bm_flags & BM_FLAG_RLE_BIG )
1951 sbits += (int)INTEL_SHORT(*((short *)&(bm->bm_data[4+(i*data_offset)])));
1953 sbits += (int)bm->bm_data[4+i];
1958 ogl_loadtexture(buf, 0, 0, bm->gltexture, bm->bm_flags, 0);
1961 void ogl_loadbmtexture(grs_bitmap *bm)
1963 ogl_loadbmtexture_f(bm, OGL_FLAG_MIPMAP);
1966 void ogl_freetexture(ogl_texture *gltexture)
1968 if (gltexture->handle>0) {
1970 glmprintf((0,"ogl_freetexture(%p):%i (last rend %is) (%i left)\n",gltexture,gltexture->handle,(GameTime-gltexture->lastrend)/f1_0,r_texcount));
1971 glDeleteTextures( 1, &gltexture->handle );
1972 // gltexture->handle=0;
1973 ogl_reset_texture(gltexture);
1976 void ogl_freebmtexture(grs_bitmap *bm){
1978 ogl_freetexture(bm->gltexture);
1981 // glmprintf((0,"ogl_freebmtexture(%p,%p):%i (%i left)\n",bm->bm_data,&bm->gltexture,bm->gltexture,r_texcount));
1982 // glDeleteTextures( 1, &bm->gltexture );
1983 // bm->gltexture=-1;