3 * Graphics support functions for OpenGL.
18 #if defined(__APPLE__) && defined(__MACH__)
19 #include <OpenGL/gl.h>
20 #include <OpenGL/glu.h>
21 #include <OpenGL/glext.h>
32 #include "../../3d/globvars.h"
44 //change to 1 for lots of spew.
46 #define glmprintf(a) mprintf(a)
55 #if defined(_WIN32) || (defined(__APPLE__) && defined(__MACH__)) || defined(__sun__) || defined(macintosh)
56 #define cosf(a) cos(a)
57 #define sinf(a) sin(a)
60 unsigned char *ogl_pal=gr_palette;
62 int GL_texmagfilt=GL_NEAREST;
63 int GL_texminfilt=GL_NEAREST;
64 float GL_texanisofilt = 0;
67 unsigned last_width = ~0u, last_height = ~0u;
68 int GL_TEXTURE_2D_enabled=-1;
69 int GL_texclamp_enabled=-1;
71 extern int gr_badtexture;
72 int r_texcount = 0, r_cachedtexcount = 0;
73 int ogl_alttexmerge=1;//merge textures by just printing the seperate textures?
74 int ogl_rgba_internalformat = GL_RGBA8;
75 int ogl_rgb_internalformat = GL_RGB8;
76 int ogl_intensity4_ok=1;
77 int ogl_luminance4_alpha4_ok=1;
79 int ogl_readpixels_ok=1;
80 int ogl_gettexlevelparam_ok=1;
81 #ifdef GL_ARB_multitexture
82 int ogl_arb_multitexture_ok=0;
84 #ifdef GL_SGIS_multitexture
85 int ogl_sgis_multitexture_ok=0;
87 int ogl_nv_texture_env_combine4_ok = 0;
88 #ifdef GL_NV_register_combiners
89 int ogl_nv_register_combiners_ok = 0;
91 int ogl_ext_texture_filter_anisotropic_ok = 0;
92 #ifdef GL_EXT_paletted_texture
93 int ogl_shared_palette_ok = 0;
94 int ogl_paletted_texture_ok = 0;
98 int cross_lh[2]={0,0};
99 int primary_lh[3]={0,0,0};
100 int secondary_lh[5]={0,0,0,0,0};
103 #define OGL_BINDTEXTURE(a) if(gr_badtexture>0) glBindTexture(GL_TEXTURE_2D, 0);\
104 else if(a!=lastbound) {glBindTexture(GL_TEXTURE_2D, a);lastbound=a;}*/
105 #define OGL_BINDTEXTURE(a) if(gr_badtexture>0) glBindTexture(GL_TEXTURE_2D, 0);\
106 else glBindTexture(GL_TEXTURE_2D, a);
109 ogl_texture ogl_texture_list[OGL_TEXTURE_LIST_SIZE];
110 int ogl_texture_list_cur;
112 /* some function prototypes */
114 //#define OGLTEXBUFSIZE (1024*1024*4)
115 #define OGLTEXBUFSIZE (2048*2048*4)
116 extern GLubyte texbuf[OGLTEXBUFSIZE];
117 //void ogl_filltexbuf(unsigned char *data,GLubyte *texp,int width,int height,int twidth,int theight);
118 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);
119 void ogl_loadbmtexture(grs_bitmap *bm);
120 //void ogl_loadtexture(unsigned char * data, int width, int height,int dxo,intdyo , int *texid,float *u,float *v,char domipmap,float prio);
121 void ogl_loadtexture(unsigned char *data, int dxo, int dyo, ogl_texture *tex, int bm_flags, int data_format);
122 void ogl_freetexture(ogl_texture *gltexture);
123 void ogl_do_palfx(void);
125 void ogl_init_texture_stats(ogl_texture* t){
126 t->prio=0.3;//default prio
130 void ogl_init_texture(ogl_texture* t, int w, int h, int flags)
133 if (flags & OGL_FLAG_NOCOLOR)
135 // use GL_INTENSITY instead of GL_RGB
136 if (flags & OGL_FLAG_ALPHA)
138 if (ogl_intensity4_ok)
140 t->internalformat = GL_INTENSITY4;
141 t->format = GL_LUMINANCE;
143 else if (ogl_luminance4_alpha4_ok)
145 t->internalformat = GL_LUMINANCE4_ALPHA4;
146 t->format = GL_LUMINANCE_ALPHA;
148 else if (ogl_rgba2_ok)
150 t->internalformat = GL_RGBA2;
155 t->internalformat = ogl_rgba_internalformat;
161 // there are certainly smaller formats we could use here, but nothing needs it ATM.
162 t->internalformat = ogl_rgb_internalformat;
168 if (flags & OGL_FLAG_ALPHA)
170 t->internalformat = ogl_rgba_internalformat;
175 t->internalformat = ogl_rgb_internalformat;
179 t->wrapstate[0] = -1;
180 t->wrapstate[1] = -1;
183 t->wantmip = flags & OGL_FLAG_MIPMAP;
184 ogl_init_texture_stats(t);
187 void ogl_reset_texture(ogl_texture* t)
189 ogl_init_texture(t, 0, 0, 0);
192 void ogl_reset_texture_stats_internal(void){
194 for (i=0;i<OGL_TEXTURE_LIST_SIZE;i++)
195 if (ogl_texture_list[i].handle>0){
196 ogl_init_texture_stats(&ogl_texture_list[i]);
199 void ogl_init_texture_list_internal(void){
201 ogl_texture_list_cur=0;
202 for (i=0;i<OGL_TEXTURE_LIST_SIZE;i++)
203 ogl_reset_texture(&ogl_texture_list[i]);
205 void ogl_smash_texture_list_internal(void){
208 memset(cross_lh,0,sizeof(cross_lh));
209 memset(primary_lh,0,sizeof(primary_lh));
210 memset(secondary_lh,0,sizeof(secondary_lh));
211 for (i=0;i<OGL_TEXTURE_LIST_SIZE;i++){
212 if (ogl_texture_list[i].handle>0){
213 glDeleteTextures( 1, &ogl_texture_list[i].handle );
214 ogl_texture_list[i].handle=0;
216 ogl_texture_list[i].wrapstate[0] = -1;
217 ogl_texture_list[i].wrapstate[1] = -1;
220 void ogl_vivify_texture_list_internal(void){
224 for (i=0;i<OGL_TEXTURE_LIST_SIZE;i++){
225 t=&ogl_texture_list[i];
226 if (t->w>0){//erk, realised this can't be done since we'd need the texture bm_data too. hmmm.
227 ogl_loadbmtexture(t);
232 ogl_texture* ogl_get_free_texture(void){
234 for (i=0;i<OGL_TEXTURE_LIST_SIZE;i++){
235 if (ogl_texture_list[ogl_texture_list_cur].handle<=0 && ogl_texture_list[ogl_texture_list_cur].w==0)
236 return &ogl_texture_list[ogl_texture_list_cur];
237 if (++ogl_texture_list_cur>=OGL_TEXTURE_LIST_SIZE)
238 ogl_texture_list_cur=0;
240 Error("OGL: texture list full!\n");
243 int ogl_texture_stats(void){
244 int used = 0, usedother = 0, usedidx = 0, usedrgb = 0, usedrgba = 0;
245 int databytes = 0, truebytes = 0, datatexel = 0, truetexel = 0, i;
246 int prio0=0,prio1=0,prio2=0,prio3=0,prioh=0;
249 for (i=0;i<OGL_TEXTURE_LIST_SIZE;i++){
250 t=&ogl_texture_list[i];
253 datatexel+=t->w*t->h;
254 truetexel+=t->tw*t->th;
255 databytes+=t->bytesu;
257 if (t->prio<0.299)prio0++;
258 else if (t->prio<0.399)prio1++;
259 else if (t->prio<0.499)prio2++;
260 else if (t->prio<0.599)prio3++;
262 if (t->format == GL_RGBA)
264 else if (t->format == GL_RGB)
266 else if (t->format == GL_COLOR_INDEX)
276 GLint idx, r, g, b, a, dbl, depth;
277 int res, colorsize, depthsize;
279 res = SWIDTH * SHEIGHT;
280 glGetIntegerv(GL_INDEX_BITS, &idx);
281 glGetIntegerv(GL_RED_BITS, &r);
282 glGetIntegerv(GL_GREEN_BITS, &g);
283 glGetIntegerv(GL_BLUE_BITS, &b);
284 glGetIntegerv(GL_ALPHA_BITS, &a);
285 glGetIntegerv(GL_DOUBLEBUFFER, &dbl);
287 glGetIntegerv(GL_DEPTH_BITS, &depth);
288 colorsize = (idx * res * dbl) / 8;
289 depthsize = res * depth / 8;
290 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);
291 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);
292 gr_printf(5, GAME_FONT->ft_h * 16 + 3 * 16, "total=%iK", (colorsize + depthsize + truebytes) / 1024);
294 // 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));
297 int ogl_mem_target=-1;
298 void ogl_clean_texture_cache(void){
303 if (ogl_mem_target<0){
309 bytes=ogl_texture_stats();
310 while (bytes>ogl_mem_target){
311 for (i=0;i<OGL_TEXTURE_LIST_SIZE;i++){
312 t=&ogl_texture_list[i];
314 if (t->lastrend+f1_0*time<GameTime){
317 if (bytes<ogl_mem_target)
323 Error("not enough mem?");
328 void ogl_bindbmtex(grs_bitmap *bm){
329 if (bm->gltexture==NULL || bm->gltexture->handle<=0)
330 ogl_loadbmtexture(bm);
331 OGL_BINDTEXTURE(bm->gltexture->handle);
332 bm->gltexture->lastrend=GameTime;
333 bm->gltexture->numrend++;
334 //// if (bm->gltexture->numrend==80 || bm->gltexture->numrend==4000 || bm->gltexture->numrend==80000){
335 // if (bm->gltexture->numrend==100){
336 // bm->gltexture->prio+=0.1;
337 //// glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_PRIORITY,bm->gltexture->prio);
338 // glPrioritizeTextures(1,&bm->gltexture->handle,&bm->gltexture->prio);
341 //gltexture MUST be bound first
342 void ogl_texwrap(ogl_texture *gltexture,int state)
344 if (gltexture->wrapstate[active_texture_unit] != state || gltexture->numrend < 1)
346 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, state);
347 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, state);
348 gltexture->wrapstate[active_texture_unit] = state;
352 //crude texture precaching
353 //handles: powerups, walls, weapons, polymodels, etc.
354 //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.
355 //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
358 void ogl_cache_polymodel_textures(int model_num)
365 po = &Polygon_models[model_num];
366 for (i=0;i<po->n_textures;i++) {
367 // texture_list_index[i] = ObjBitmaps[ObjBitmapPtrs[po->first_texture+i]];
368 ogl_loadbmtexture(&GameBitmaps[ObjBitmaps[ObjBitmapPtrs[po->first_texture+i]].index]);
371 void ogl_cache_vclip_textures(vclip *vc){
373 for (i=0;i<vc->num_frames;i++){
374 PIGGY_PAGE_IN(vc->frames[i]);
375 ogl_loadbmtexture(&GameBitmaps[vc->frames[i].index]);
379 void ogl_cache_vclipn_textures(int i)
381 if (i >= 0 && i < VCLIP_MAXNUM)
382 ogl_cache_vclip_textures(&Vclip[i]);
385 void ogl_cache_weapon_textures(int weapon_type)
391 w = &Weapon_info[weapon_type];
392 ogl_cache_vclipn_textures(w->flash_vclip);
393 ogl_cache_vclipn_textures(w->robot_hit_vclip);
394 ogl_cache_vclipn_textures(w->wall_hit_vclip);
395 if (w->render_type==WEAPON_RENDER_VCLIP)
396 ogl_cache_vclipn_textures(w->weapon_vclip);
397 else if (w->render_type == WEAPON_RENDER_POLYMODEL)
399 ogl_cache_polymodel_textures(w->model_num);
400 ogl_cache_polymodel_textures(w->model_num_inner);
404 void ogl_cache_level_textures(void)
413 ogl_reset_texture_stats_internal();//loading a new lev should reset textures
415 for (i=0,ec=Effects;i<Num_effects;i++,ec++) {
416 ogl_cache_vclipn_textures(Effects[i].dest_vclip);
417 if ((Effects[i].changing_wall_texture == -1) && (Effects[i].changing_object_texture==-1) )
419 if (ec->vc.num_frames>max_efx)
420 max_efx=ec->vc.num_frames;
422 glmprintf((0,"max_efx:%i\n",max_efx));
423 for (ef=0;ef<max_efx;ef++){
424 for (i=0,ec=Effects;i<Num_effects;i++,ec++) {
425 if ((Effects[i].changing_wall_texture == -1) && (Effects[i].changing_object_texture==-1) )
427 // if (ec->vc.num_frames>max_efx)
428 // max_efx=ec->vc.num_frames;
431 do_special_effects();
433 for (seg=0;seg<Num_segments;seg++){
434 for (side=0;side<MAX_SIDES_PER_SEGMENT;side++){
435 sidep=&Segments[seg].sides[side];
436 tmap1=sidep->tmap_num;
437 tmap2=sidep->tmap_num2;
438 if (tmap1<0 || tmap1>=NumTextures){
439 glmprintf((0,"ogl_cache_level_textures %i %i %i %i\n",seg,side,tmap1,NumTextures));
443 PIGGY_PAGE_IN(Textures[tmap1]);
444 bm = &GameBitmaps[Textures[tmap1].index];
446 PIGGY_PAGE_IN(Textures[tmap2&0x3FFF]);
447 bm2 = &GameBitmaps[Textures[tmap2&0x3FFF].index];
448 if (ogl_alttexmerge == 0 || (!OGL_SUPER_TRANSPARENT_OK && (bm2->bm_flags & BM_FLAG_SUPER_TRANSPARENT)))
449 bm = texmerge_get_cached_bitmap( tmap1, tmap2 );
451 ogl_loadbmtexture(bm2);
453 // 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));
455 ogl_loadbmtexture(bm);
458 glmprintf((0,"finished ef:%i\n",ef));
460 reset_special_effects();
461 init_special_effects();
465 // always have lasers, concs, flares. Always shows player appearance, and at least concs are always available to disappear.
466 ogl_cache_weapon_textures(Primary_weapon_to_weapon_info[LASER_INDEX]);
467 ogl_cache_weapon_textures(Secondary_weapon_to_weapon_info[CONCUSSION_INDEX]);
468 ogl_cache_weapon_textures(FLARE_ID);
469 ogl_cache_vclipn_textures(VCLIP_PLAYER_APPEARANCE);
470 ogl_cache_vclipn_textures(VCLIP_POWERUP_DISAPPEARANCE);
471 ogl_cache_polymodel_textures(Player_ship->model_num);
472 ogl_cache_vclipn_textures(Player_ship->expl_vclip_num);
474 for (i=0;i<Highest_object_index;i++){
475 if(Objects[i].render_type==RT_POWERUP){
476 ogl_cache_vclipn_textures(Objects[i].rtype.vclip_info.vclip_num);
477 switch (Objects[i].id){
479 ogl_cache_weapon_textures(Primary_weapon_to_weapon_info[LASER_INDEX]);
483 case POW_VULCAN_WEAPON:
484 ogl_cache_weapon_textures(Primary_weapon_to_weapon_info[VULCAN_INDEX]);
486 case POW_SPREADFIRE_WEAPON:
487 ogl_cache_weapon_textures(Primary_weapon_to_weapon_info[SPREADFIRE_INDEX]);
489 case POW_PLASMA_WEAPON:
490 ogl_cache_weapon_textures(Primary_weapon_to_weapon_info[PLASMA_INDEX]);
492 case POW_FUSION_WEAPON:
493 ogl_cache_weapon_textures(Primary_weapon_to_weapon_info[FUSION_INDEX]);
495 /* case POW_MISSILE_1:
497 ogl_cache_weapon_textures(Secondary_weapon_to_weapon_info[CONCUSSION_INDEX]);
499 case POW_PROXIMITY_WEAPON:
500 ogl_cache_weapon_textures(Secondary_weapon_to_weapon_info[PROXIMITY_INDEX]);
502 case POW_HOMING_AMMO_1:
503 case POW_HOMING_AMMO_4:
504 ogl_cache_weapon_textures(Primary_weapon_to_weapon_info[HOMING_INDEX]);
506 case POW_SMARTBOMB_WEAPON:
507 ogl_cache_weapon_textures(Secondary_weapon_to_weapon_info[SMART_INDEX]);
509 case POW_MEGA_WEAPON:
510 ogl_cache_weapon_textures(Secondary_weapon_to_weapon_info[MEGA_INDEX]);
514 else if(Objects[i].render_type==RT_POLYOBJ){
515 //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);
516 if (Objects[i].type == OBJ_ROBOT)
518 ogl_cache_vclipn_textures(Robot_info[Objects[i].id].exp1_vclip_num);
519 ogl_cache_vclipn_textures(Robot_info[Objects[i].id].exp2_vclip_num);
520 ogl_cache_weapon_textures(Robot_info[Objects[i].id].weapon_type);
522 if (Objects[i].rtype.pobj_info.tmap_override != -1)
523 ogl_loadbmtexture(&GameBitmaps[Textures[Objects[i].rtype.pobj_info.tmap_override].index]);
525 ogl_cache_polymodel_textures(Objects[i].rtype.pobj_info.model_num);
529 glmprintf((0,"finished caching\n"));
530 r_cachedtexcount = r_texcount;
533 int r_polyc,r_tpolyc,r_bitmapc,r_ubitmapc,r_ubitbltc,r_upixelc;
534 #define f2glf(x) (f2fl(x))
536 bool g3_draw_line(g3s_point *p0,g3s_point *p1)
539 c=grd_curcanv->cv_color;
540 OGL_DISABLE(TEXTURE_2D);
541 glColor3f(PAL2Tr(c),PAL2Tg(c),PAL2Tb(c));
543 glVertex3f(f2glf(p0->p3_vec.x),f2glf(p0->p3_vec.y),-f2glf(p0->p3_vec.z));
544 glVertex3f(f2glf(p1->p3_vec.x),f2glf(p1->p3_vec.y),-f2glf(p1->p3_vec.z));
548 void ogl_drawcircle2(int nsides,int type,float xsc,float xo,float ysc,float yo){
552 for (i=0; i<nsides; i++) {
553 ang = 2.0*M_PI*i/nsides;
554 glVertex2f(cosf(ang)*xsc+xo,sinf(ang)*ysc+yo);
558 void ogl_drawcircle(int nsides,int type){
562 for (i=0; i<nsides; i++) {
563 ang = 2.0*M_PI*i/nsides;
564 glVertex2f(cosf(ang),sinf(ang));
568 int circle_list_init(int nsides,int type,int mode) {
569 int hand=glGenLists(1);
570 glNewList(hand, mode);
571 /* draw a unit radius circle in xy plane centered on origin */
572 ogl_drawcircle(nsides,type);
576 float bright_g[4]={ 32.0/256, 252.0/256, 32.0/256};
577 float dark_g[4]={ 32.0/256, 148.0/256, 32.0/256};
578 float darker_g[4]={ 32.0/256, 128.0/256, 32.0/256};
579 void ogl_draw_reticle(int cross,int primary,int secondary){
580 float scale=(float)Canvas_height/(float)grd_curscreen->sc_h;
582 // glTranslatef(0.5,0.5,0);
583 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);
584 glScalef(scale/320.0,scale/200.0,scale);//the positions are based upon the standard reticle at 320x200 res.
586 OGL_DISABLE(TEXTURE_2D);
588 if (!cross_lh[cross]){
589 cross_lh[cross]=glGenLists(1);
590 glNewList(cross_lh[cross], GL_COMPILE_AND_EXECUTE);
593 glColor3fv(darker_g);
594 glVertex2f(-4.0,4.0);
596 glColor3fv(bright_g);
599 glVertex2f(-2.0,2.0);
603 glVertex2f(-3.0,-2.0);
605 glColor3fv(bright_g);
606 glVertex2f(-2.0,-1.0);
609 glColor3fv(darker_g);
612 glColor3fv(bright_g);
619 glVertex2f(3.0,-2.0);
621 glColor3fv(bright_g);
622 glVertex2f(2.0,-1.0);
627 glCallList(cross_lh[cross]);
629 // if (Canvas_height>200)
630 // glLineWidth(Canvas_height/(float)200);
631 if (!primary_lh[primary]){
632 primary_lh[primary]=glGenLists(1);
633 glNewList(primary_lh[primary], GL_COMPILE_AND_EXECUTE);
638 glVertex2f(-14.0,-8.0);
639 glVertex2f(-8.0,-5.0);
641 glVertex2f(14.0,-8.0);
642 glVertex2f(8.0,-5.0);
647 glColor3fv(bright_g);
649 ogl_drawcircle2(6,GL_POLYGON,1.5,-7.0,1.5,-5.0);
651 ogl_drawcircle2(6,GL_POLYGON,1.5,7.0,1.5,-5.0);
655 glColor3fv(bright_g);
657 ogl_drawcircle2(4,GL_POLYGON,1.0,-14.0,1.0,-8.0);
659 ogl_drawcircle2(4,GL_POLYGON,1.0,14.0,1.0,-8.0);
663 glCallList(primary_lh[primary]);
664 // if (Canvas_height>200)
667 if (!secondary_lh[secondary]){
668 secondary_lh[secondary]=glGenLists(1);
669 glNewList(secondary_lh[secondary], GL_COMPILE_AND_EXECUTE);
673 glColor3fv(darker_g);
675 glColor3fv(bright_g);
676 ogl_drawcircle2(8,GL_LINE_LOOP,2.0,-10.0,2.0,-1.0);
679 glColor3fv(darker_g);
681 glColor3fv(bright_g);
682 ogl_drawcircle2(8,GL_LINE_LOOP,2.0,10.0,2.0,-1.0);
684 //bottom/middle secondary
686 glColor3fv(darker_g);
688 glColor3fv(bright_g);
689 ogl_drawcircle2(8,GL_LINE_LOOP,2.0,0.0,2.0,-7.0);
693 glCallList(secondary_lh[secondary]);
697 int g3_draw_sphere(g3s_point *pnt,fix rad){
699 c=grd_curcanv->cv_color;
700 OGL_DISABLE(TEXTURE_2D);
701 // glPointSize(f2glf(rad));
702 glColor3f(CPAL2Tr(c),CPAL2Tg(c),CPAL2Tb(c));
703 // glBegin(GL_POINTS);
704 // glVertex3f(f2glf(pnt->p3_vec.x),f2glf(pnt->p3_vec.y),-f2glf(pnt->p3_vec.z));
707 glTranslatef(f2glf(pnt->p3_vec.x),f2glf(pnt->p3_vec.y),-f2glf(pnt->p3_vec.z));
708 glScalef(f2glf(rad),f2glf(rad),f2glf(rad));
709 if (!sphereh) sphereh=circle_list_init(20,GL_POLYGON,GL_COMPILE_AND_EXECUTE);
710 else glCallList(sphereh);
715 int gr_ucircle(fix xc1, fix yc1, fix r1)
718 c=grd_curcanv->cv_color;
719 OGL_DISABLE(TEXTURE_2D);
720 glColor3f(CPAL2Tr(c),CPAL2Tg(c),CPAL2Tb(c));
723 (f2fl(xc1) + grd_curcanv->cv_bitmap.bm_x + 0.5) / (float)last_width,
724 1.0 - (f2fl(yc1) + grd_curcanv->cv_bitmap.bm_y + 0.5) / (float)last_height,0);
725 glScalef(f2fl(r1) / last_width, f2fl(r1) / last_height, 1.0);
726 ogl_drawcircle(10 + 2 * (int)(M_PI * f2fl(r1) / 19), GL_LINE_LOOP);
730 int gr_circle(fix xc1,fix yc1,fix r1){
731 return gr_ucircle(xc1,yc1,r1);
734 bool g3_draw_poly(int nv,g3s_point **pointlist)
738 c=grd_curcanv->cv_color;
739 // glColor3f((gr_palette[c*3] + gr_palette_gamma.intval) / 63.0, (gr_palette[c*3+1] + gr_palette_gamma.intval) / 63.0, (gr_palette[c*3+2] + gr_palette_gamma.intval) / 63.0);
740 OGL_DISABLE(TEXTURE_2D);
741 if (Gr_scanline_darkening_level >= GR_FADE_LEVELS)
742 glColor3f(PAL2Tr(c), PAL2Tg(c), PAL2Tb(c));
744 glColor4f(PAL2Tr(c), PAL2Tg(c), PAL2Tb(c), 1.0 - (float)Gr_scanline_darkening_level / ((float)GR_FADE_LEVELS - 1.0));
745 glBegin(GL_TRIANGLE_FAN);
747 // glVertex3f(f2glf(pointlist[c]->p3_vec.x),f2glf(pointlist[c]->p3_vec.y),f2glf(pointlist[c]->p3_vec.z));
748 glVertex3f(f2glf(pointlist[c]->p3_vec.x),f2glf(pointlist[c]->p3_vec.y),-f2glf(pointlist[c]->p3_vec.z));
754 void gr_upoly_tmap(int nverts, int *vert ){
755 mprintf((0,"gr_upoly_tmap: unhandled\n"));//should never get called
757 void draw_tmap_flat(grs_bitmap *bm,int nv,g3s_point **vertlist){
758 mprintf((0,"draw_tmap_flat: unhandled\n"));//should never get called
760 extern void (*tmap_drawer_ptr)(grs_bitmap *bm,int nv,g3s_point **vertlist);
761 bool g3_draw_tmap(int nv,g3s_point **pointlist,g3s_uvl *uvl_list,grs_bitmap *bm)
765 if (tmap_drawer_ptr==draw_tmap_flat){
766 /* fix average_light=0;
769 average_light += uvl_list[i].l;*/
770 OGL_DISABLE(TEXTURE_2D);
771 // glmprintf((0,"Gr_scanline_darkening_level=%i %f\n",Gr_scanline_darkening_level,Gr_scanline_darkening_level/(float)NUM_LIGHTING_LEVELS));
772 glColor4f(0,0,0,1.0-(Gr_scanline_darkening_level/(float)NUM_LIGHTING_LEVELS));
773 //glColor4f(0,0,0,f2fl(average_light/nv));
774 glBegin(GL_TRIANGLE_FAN);
776 // glColor4f(0,0,0,f2fl(uvl_list[c].l));
777 // glTexCoord2f(f2glf(uvl_list[c].u),f2glf(uvl_list[c].v));
778 glVertex3f(f2glf(pointlist[c]->p3_vec.x),f2glf(pointlist[c]->p3_vec.y),-f2glf(pointlist[c]->p3_vec.z));
781 }else if (tmap_drawer_ptr==draw_tmap){
783 /* if (bm->bm_w !=64||bm->bm_h!=64)
784 printf("g3_draw_tmap w %i h %i\n",bm->bm_w,bm->bm_h);*/
785 OGL_ENABLE(TEXTURE_2D);
787 ogl_texwrap(bm->gltexture,GL_REPEAT);
788 glBegin(GL_TRIANGLE_FAN);
790 if (bm->bm_flags&BM_FLAG_NO_LIGHTING){
793 //l = f2fl(uvl_list[c].l) + gr_palette_gamma.intval / 63.0;
794 l=f2fl(uvl_list[c].l);
797 glTexCoord2f(f2glf(uvl_list[c].u),f2glf(uvl_list[c].v));
798 //glVertex3f(f2glf(pointlist[c]->p3_vec.x),f2glf(pointlist[c]->p3_vec.y),f2glf(pointlist[c]->p3_vec.z));
799 glVertex3f(f2glf(pointlist[c]->p3_vec.x),f2glf(pointlist[c]->p3_vec.y),-f2glf(pointlist[c]->p3_vec.z));
803 mprintf((0,"g3_draw_tmap: unhandled tmap_drawer %p\n",tmap_drawer_ptr));
808 int active_texture_unit = 0;
810 void ogl_setActiveTexture(int t)
812 if (ogl_arb_multitexture_ok)
814 #ifdef GL_ARB_multitexture
816 glActiveTextureARB(GL_TEXTURE0_ARB);
818 glActiveTextureARB(GL_TEXTURE1_ARB);
821 else if (ogl_sgis_multitexture_ok)
823 #ifdef GL_SGIS_multitexture
825 glSelectTextureSGIS(GL_TEXTURE0_SGIS);
827 glSelectTextureSGIS(GL_TEXTURE1_SGIS);
830 active_texture_unit = t;
833 void ogl_MultiTexCoord2f(int t, float u, float v)
835 if (ogl_arb_multitexture_ok)
837 #ifdef GL_ARB_multitexture
839 glMultiTexCoord2fARB(GL_TEXTURE0_ARB, u, v);
841 glMultiTexCoord2fARB(GL_TEXTURE1_ARB, u, v);
844 else if (ogl_sgis_multitexture_ok)
846 #ifdef GL_SGIS_multitexture
848 glMultiTexCoord2fSGIS(GL_TEXTURE0_SGIS, u, v);
850 glMultiTexCoord2fSGIS(GL_TEXTURE1_SGIS, u, v);
855 bool g3_draw_tmap_2(int nv, g3s_point **pointlist, g3s_uvl *uvl_list, grs_bitmap *bmbot, grs_bitmap *bm, int orient)
857 #if ((defined(GL_NV_register_combiners) || defined(GL_NV_texture_env_combine4)) && (defined(GL_ARB_multitexture) || defined(GL_SGIS_multitexture)))
858 if ((/*ogl_nv_register_combiners_ok ||*/ ogl_nv_texture_env_combine4_ok) && (ogl_arb_multitexture_ok || ogl_sgis_multitexture_ok))
863 if (tmap_drawer_ptr != draw_tmap)
868 //ogl_setActiveTexture(0);
869 OGL_ENABLE(TEXTURE_2D);
870 ogl_bindbmtex(bmbot);
871 ogl_texwrap(bmbot->gltexture, GL_REPEAT);
872 // GL_MODULATE is fine for texture 0
874 ogl_setActiveTexture(1);
875 glEnable(GL_TEXTURE_2D);
877 ogl_texwrap(bm->gltexture,GL_REPEAT);
879 #ifdef GL_NV_register_combiners
880 if (ogl_nv_register_combiners_ok)
882 glEnable(GL_REGISTER_COMBINERS_NV);
883 glCombinerParameteriNV(GL_NUM_GENERAL_COMBINERS_NV, 1);
884 // spare0 = tex0 * (1-alpha1) + tex1 * alpha1
885 glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_A_NV, GL_TEXTURE0_ARB, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
886 glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_B_NV, GL_TEXTURE1_ARB, GL_UNSIGNED_INVERT_NV, GL_ALPHA);
887 glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_C_NV, GL_TEXTURE1_ARB, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
888 glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_D_NV, GL_TEXTURE1_ARB, GL_UNSIGNED_IDENTITY_NV, GL_ALPHA);
890 GL_COMBINER0_NV, //GLenum stage
891 GL_RGB, //GLenum portion,
892 GL_DISCARD_NV, //GLenum abOutput,
893 GL_DISCARD_NV, //GLenum cdOutput,
894 GL_SPARE0_NV, //GLenum sumOutput,
895 GL_NONE, //GLenum scale,
896 GL_NONE, //GLenum bias,
897 GL_FALSE, //GLboolean abDotProduct,
898 GL_FALSE, //GLboolean cdDotProduct,
899 GL_FALSE //GLboolean muxSum
901 // out = spare0 * color
902 // ( out = AB + (1-A)C + D )
903 glFinalCombinerInputNV(GL_VARIABLE_A_NV, GL_SPARE0_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
904 glFinalCombinerInputNV(GL_VARIABLE_B_NV, GL_PRIMARY_COLOR_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
905 glFinalCombinerInputNV(GL_VARIABLE_C_NV, GL_ZERO, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
906 glFinalCombinerInputNV(GL_VARIABLE_D_NV, GL_ZERO, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
908 if (bm->bm_flags & BM_FLAG_SUPER_TRANSPARENT)
910 // out = alpha0*(1-tex1) + alpha1
911 glCombinerInputNV(GL_COMBINER0_NV, GL_ALPHA, GL_VARIABLE_A_NV, GL_TEXTURE0_ARB, GL_UNSIGNED_IDENTITY_NV, GL_ALPHA);
912 glCombinerInputNV(GL_COMBINER0_NV, GL_ALPHA, GL_VARIABLE_B_NV, GL_TEXTURE1_ARB, GL_UNSIGNED_INVERT_NV, GL_BLUE);
913 glCombinerInputNV(GL_COMBINER0_NV, GL_ALPHA, GL_VARIABLE_C_NV, GL_TEXTURE1_ARB, GL_UNSIGNED_IDENTITY_NV, GL_ALPHA);
914 glCombinerInputNV(GL_COMBINER0_NV, GL_ALPHA, GL_VARIABLE_D_NV, GL_ZERO, GL_UNSIGNED_INVERT_NV, GL_ALPHA);
918 // out = alpha0 + alpha1
919 glCombinerInputNV(GL_COMBINER0_NV, GL_ALPHA, GL_VARIABLE_A_NV, GL_TEXTURE0_ARB, GL_UNSIGNED_IDENTITY_NV, GL_ALPHA);
920 glCombinerInputNV(GL_COMBINER0_NV, GL_ALPHA, GL_VARIABLE_B_NV, GL_ZERO, GL_UNSIGNED_INVERT_NV, GL_ALPHA);
921 glCombinerInputNV(GL_COMBINER0_NV, GL_ALPHA, GL_VARIABLE_C_NV, GL_TEXTURE1_ARB, GL_UNSIGNED_IDENTITY_NV, GL_ALPHA);
922 glCombinerInputNV(GL_COMBINER0_NV, GL_ALPHA, GL_VARIABLE_D_NV, GL_ZERO, GL_UNSIGNED_INVERT_NV, GL_ALPHA);
925 GL_COMBINER0_NV, //GLenum stage
926 GL_ALPHA, //GLenum portion,
927 GL_DISCARD_NV, //GLenum abOutput,
928 GL_DISCARD_NV, //GLenum cdOutput,
929 GL_SPARE0_NV, //GLenum sumOutput,
930 GL_NONE, //GLenum scale,
931 GL_NONE, //GLenum bias,
932 GL_FALSE, //GLboolean abDotProduct,
933 GL_FALSE, //GLboolean cdDotProduct,
934 GL_FALSE //GLboolean muxSum
936 glFinalCombinerInputNV(GL_VARIABLE_G_NV, GL_SPARE0_NV, GL_UNSIGNED_IDENTITY_NV, GL_ALPHA);
941 //http://oss.sgi.com/projects/ogl-sample/registry/NV/texture_env_combine4.txt
942 //only GL_NV_texture_env_combine4 lets us do what we need:
943 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE4_NV);
945 //multiply top texture by color(vertex lighting) and add bottom texture(where alpha says to)
946 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_ADD);
948 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE);
949 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PRIMARY_COLOR_EXT);
950 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_EXT, GL_TEXTURE);
951 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE3_RGB_NV, GL_PREVIOUS_EXT);
953 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, GL_SRC_COLOR);
954 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_EXT, GL_SRC_COLOR);
955 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_EXT, GL_ONE_MINUS_SRC_ALPHA);
956 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND3_RGB_NV, GL_SRC_COLOR);
958 //add up alpha channels
959 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_ADD);
961 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_TEXTURE);
962 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_EXT, GL_ZERO);
963 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA_EXT, GL_PREVIOUS_EXT);
964 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE3_ALPHA_NV, GL_ZERO);
966 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT, GL_SRC_ALPHA);
967 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_EXT, GL_ONE_MINUS_SRC_ALPHA);
968 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA_EXT, GL_SRC_ALPHA);
969 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND3_ALPHA_NV, GL_ONE_MINUS_SRC_ALPHA);
972 // GL_DECAL works sorta ok but the top texture is fullbright.
973 //glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
975 // GL_ARB_texture_env_combine comes close, but doesn't quite make it.
976 //glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
978 //// this gives effect like GL_DECAL:
979 //glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_INTERPOLATE);
980 //glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
981 //glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB);
982 //glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_TEXTURE);
985 // this properly shades the top texture, but the bottom texture doesn't get through.
986 //glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
987 //glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PRIMARY_COLOR_ARB);
988 //glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE);
992 //glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_ADD);
993 //glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
994 //glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_PREVIOUS_ARB);
996 glBegin(GL_TRIANGLE_FAN);
1000 u1=1.0-f2glf(uvl_list[c].v);
1001 v1=f2glf(uvl_list[c].u);
1004 u1=1.0-f2glf(uvl_list[c].u);
1005 v1=1.0-f2glf(uvl_list[c].v);
1008 u1=f2glf(uvl_list[c].v);
1009 v1=1.0-f2glf(uvl_list[c].u);
1012 u1=f2glf(uvl_list[c].u);
1013 v1=f2glf(uvl_list[c].v);
1016 if (bm->bm_flags&BM_FLAG_NO_LIGHTING){
1019 l=f2fl(uvl_list[c].l);
1022 ogl_MultiTexCoord2f(0, f2glf(uvl_list[c].u), f2glf(uvl_list[c].v));
1023 ogl_MultiTexCoord2f(1, u1, v1);
1024 //glVertex3f(f2glf(pointlist[c]->p3_vec.x),f2glf(pointlist[c]->p3_vec.y),f2glf(pointlist[c]->p3_vec.z));
1025 //glVertex3f(f2glf(pointlist[c]->p3_vec.x),f2glf(pointlist[c]->p3_vec.y),f2glf(pointlist[c]->p3_vec.z));
1026 glVertex3f(f2glf(pointlist[c]->p3_vec.x),f2glf(pointlist[c]->p3_vec.y),-f2glf(pointlist[c]->p3_vec.z));
1029 //ogl_setActiveTexture(1); // still the active texture
1030 #ifdef GL_NV_register_combiners
1031 if (ogl_nv_register_combiners_ok)
1033 glDisable(GL_REGISTER_COMBINERS_NV);
1038 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
1040 glDisable(GL_TEXTURE_2D);
1041 ogl_setActiveTexture(0);
1049 g3_draw_tmap(nv,pointlist,uvl_list,bmbot);//draw the bottom texture first.. could be optimized with multitexturing..
1052 /* if (bm->bm_w !=64||bm->bm_h!=64)
1053 printf("g3_draw_tmap w %i h %i\n",bm->bm_w,bm->bm_h);*/
1054 OGL_ENABLE(TEXTURE_2D);
1056 ogl_texwrap(bm->gltexture,GL_REPEAT);
1057 glBegin(GL_TRIANGLE_FAN);
1061 u1=1.0-f2glf(uvl_list[c].v);
1062 v1=f2glf(uvl_list[c].u);
1065 u1=1.0-f2glf(uvl_list[c].u);
1066 v1=1.0-f2glf(uvl_list[c].v);
1069 u1=f2glf(uvl_list[c].v);
1070 v1=1.0-f2glf(uvl_list[c].u);
1073 u1=f2glf(uvl_list[c].u);
1074 v1=f2glf(uvl_list[c].v);
1077 if (bm->bm_flags&BM_FLAG_NO_LIGHTING){
1080 //l = f2fl(uvl_list[c].l) + gr_palette_gamma.intval / 63.0;
1081 l=f2fl(uvl_list[c].l);
1084 glTexCoord2f(u1,v1);
1085 //glVertex3f(f2glf(pointlist[c]->p3_vec.x),f2glf(pointlist[c]->p3_vec.y),f2glf(pointlist[c]->p3_vec.z));
1086 //glVertex3f(f2glf(pointlist[c]->p3_vec.x),f2glf(pointlist[c]->p3_vec.y),f2glf(pointlist[c]->p3_vec.z));
1087 glVertex3f(f2glf(pointlist[c]->p3_vec.x),f2glf(pointlist[c]->p3_vec.y),-f2glf(pointlist[c]->p3_vec.z));
1094 bool g3_draw_bitmap(vms_vector *pos,fix width,fix height,grs_bitmap *bm, int orientation)
1097 vms_vector pv,v1;//,v2;
1101 // printf("g3_draw_bitmap: %f,%f,%f - ",f2glf(pos->x),f2glf(pos->y),-f2glf(pos->z));
1102 // printf("(%f,%f,%f) ",f2glf(View_position.x),f2glf(View_position.y),-f2glf(View_position.z));
1104 OGL_ENABLE(TEXTURE_2D);
1106 ogl_texwrap(bm->gltexture,GL_CLAMP);
1109 glColor3f(1.0,1.0,1.0);
1110 width = fixmul(width,Matrix_scale.x);
1111 height = fixmul(height,Matrix_scale.y);
1113 // g3_rotate_point(&p[i],pos);
1114 vm_vec_sub(&v1,pos,&View_position);
1115 vm_vec_rotate(&pv,&v1,&View_matrix);
1116 // printf(" %f,%f,%f->",f2glf(pv.x),f2glf(pv.y),-f2glf(pv.z));
1119 glTexCoord2f(0.0, 0.0);
1124 glTexCoord2f(bm->gltexture->u, 0.0);
1129 glTexCoord2f(bm->gltexture->u, bm->gltexture->v);
1134 glTexCoord2f(0.0, bm->gltexture->v);
1139 // vm_vec_rotate(&v2,&v1,&View_matrix);
1140 // vm_vec_sub(&v1,&v2,&pv);
1141 //vm_vec_sub(&v1,&pv,&v2);
1142 // vm_vec_sub(&v2,&pv,&v1);
1143 glVertex3f(f2glf(pv.x),f2glf(pv.y),-f2glf(pv.z));
1144 // printf("%f,%f,%f ",f2glf(v1.x),f2glf(v1.y),-f2glf(v1.z));
1152 bool ogl_ubitmapm_c(int x, int y,grs_bitmap *bm,int c)
1154 GLfloat xo,yo,xf,yf;
1155 GLfloat u1,u2,v1,v2;
1157 x+=grd_curcanv->cv_bitmap.bm_x;
1158 y+=grd_curcanv->cv_bitmap.bm_y;
1159 xo=x/(float)last_width;
1160 xf=(bm->bm_w+x)/(float)last_width;
1161 yo=1.0-y/(float)last_height;
1162 yf=1.0-(bm->bm_h+y)/(float)last_height;
1164 // printf("g3_draw_bitmap: %f,%f,%f - ",f2glf(pos->x),f2glf(pos->y),-f2glf(pos->z));
1165 // printf("(%f,%f,%f) ",f2glf(View_position.x),f2glf(View_position.y),-f2glf(View_position.z));
1167 /* glEnABLE(ALPHA_TEST);
1168 glAlphaFunc(GL_GREATER,0.0);*/
1170 OGL_ENABLE(TEXTURE_2D);
1172 ogl_texwrap(bm->gltexture,GL_CLAMP);
1176 if (bm->bm_w==bm->gltexture->w)
1177 u2=bm->gltexture->u;
1179 u2=(bm->bm_w+bm->bm_x)/(float)bm->gltexture->tw;
1181 u1=bm->bm_x/(float)bm->gltexture->tw;
1182 u2=(bm->bm_w+bm->bm_x)/(float)bm->gltexture->tw;
1186 if (bm->bm_h==bm->gltexture->h)
1187 v2=bm->gltexture->v;
1189 v2=(bm->bm_h+bm->bm_y)/(float)bm->gltexture->th;
1191 v1=bm->bm_y/(float)bm->gltexture->th;
1192 v2=(bm->bm_h+bm->bm_y)/(float)bm->gltexture->th;
1197 glColor3f(1.0,1.0,1.0);
1199 glColor3f(CPAL2Tr(c),CPAL2Tg(c),CPAL2Tb(c));
1200 glTexCoord2f(u1, v1); glVertex2f(xo, yo);
1201 glTexCoord2f(u2, v1); glVertex2f(xf, yo);
1202 glTexCoord2f(u2, v2); glVertex2f(xf, yf);
1203 glTexCoord2f(u1, v2); glVertex2f(xo, yf);
1205 // glDisABLE(ALPHA_TEST);
1209 bool ogl_ubitmapm(int x, int y,grs_bitmap *bm){
1210 return ogl_ubitmapm_c(x,y,bm,-1);
1211 // return ogl_ubitblt(bm->bm_w,bm->bm_h,x,y,0,0,bm,NULL);
1214 //also upsidedown, currently.
1215 bool ogl_ubitblt(int w,int h,int dx,int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest)
1217 GLfloat xo,yo;//,xs,ys;
1218 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));
1223 xo=dx/(float)last_width;
1224 // xo=dx/(float)grd_curscreen->sc_w;
1225 // xs=w/(float)last_width;
1226 //yo=1.0-dy/(float)last_height;
1227 yo=1.0-(dy+h)/(float)last_height;
1228 // ys=h/(float)last_height;
1230 // OGL_ENABLE(TEXTURE_2D);
1232 OGL_DISABLE(TEXTURE_2D);
1233 glRasterPos2f(xo,yo);
1234 ogl_filltexbuf(src->bm_data,texbuf,src->bm_w,w,h,sx,sy,w,h,GL_RGBA);
1235 glDrawPixels(w,h,GL_RGBA,GL_UNSIGNED_BYTE,texbuf);
1241 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)
1243 GLfloat xo,yo,xs,ys;
1244 GLfloat u1,v1;//,u2,v2;
1246 // unsigned char *oldpal;
1249 ogl_init_texture(&tex, sw, sh, OGL_FLAG_ALPHA);
1251 tex.lw=src->bm_rowsize;
1253 /* if (w==src->bm_w && sx==0){
1256 u1=sx/(float)src->bm_w*src->glu;
1257 u2=w/(float)src->bm_w*src->glu+u1;
1259 if (h==src->bm_h && sy==0){
1262 v1=sy/(float)src->bm_h*src->glv;
1263 v2=h/(float)src->bm_h*src->glv+v1;
1269 xo=dx/(float)last_width;
1270 xs=dw/(float)last_width;
1271 yo=1.0-dy/(float)last_height;
1272 ys=dh/(float)last_height;
1274 OGL_ENABLE(TEXTURE_2D);
1277 ogl_pal=gr_current_pal;
1278 ogl_loadtexture(src->bm_data, sx, sy, &tex, src->bm_flags, 0);
1281 OGL_BINDTEXTURE(tex.handle);
1283 ogl_texwrap(&tex,GL_CLAMP);
1286 glColor3f(1.0,1.0,1.0);
1287 glTexCoord2f(u1, v1); glVertex2f(xo, yo);
1288 glTexCoord2f(tex.u, v1); glVertex2f(xo+xs, yo);
1289 glTexCoord2f(tex.u, tex.v); glVertex2f(xo+xs, yo-ys);
1290 glTexCoord2f(u1, tex.v); glVertex2f(xo, yo-ys);
1292 ogl_freetexture(&tex);
1295 bool ogl_ubitblt(int w,int h,int dx,int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest){
1296 return ogl_ubitblt_i(w,h,dx,dy,w,h,sx,sy,src,dest);
1299 bool ogl_ubitblt_tolinear(int w,int h,int dx,int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest){
1301 unsigned char *d,*s;
1305 w1=grd_curscreen->sc_w;h1=grd_curscreen->sc_h;
1306 if (w1*h1*3>OGLTEXBUFSIZE)
1307 Error("ogl_ubitblt_tolinear: screen res larger than OGLTEXBUFSIZE\n");
1309 if (ogl_readpixels_ok>0){
1310 OGL_DISABLE(TEXTURE_2D);
1311 glReadBuffer(GL_FRONT);
1312 glReadPixels(0,0,w1,h1,GL_RGB,GL_UNSIGNED_BYTE,texbuf);
1313 // glReadPixels(sx,grd_curscreen->sc_h-(sy+h),w,h,GL_RGB,GL_UNSIGNED_BYTE,texbuf);
1314 // glReadPixels(sx,sy,w+sx,h+sy,GL_RGB,GL_UNSIGNED_BYTE,texbuf);
1316 memset(texbuf,0,w1*h1*3);
1320 d=dest->bm_data+dx+(dy+i)*dest->bm_rowsize;
1321 s=texbuf+((h1-(i+sy+1))*w1+sx)*3;
1323 *d=gr_find_closest_color(s[0]/4,s[1]/4,s[2]/4);
1330 unsigned char *d,*s,*e;
1331 if (w*h*3>OGLTEXBUFSIZE)
1332 Error("ogl_ubitblt_tolinear: size larger than OGLTEXBUFSIZE\n");
1335 #if 1//also seems to cause a mess. need to look into it a bit more..
1336 if (ogl_readpixels_ok>0){
1337 OGL_DISABLE(TEXTURE_2D);
1338 glReadBuffer(GL_FRONT);
1339 // glReadPixels(0,0,w,h,GL_RGB,GL_UNSIGNED_BYTE,texbuf);
1340 glReadPixels(sx,grd_curscreen->sc_h-(sy+h),w,h,GL_RGB,GL_UNSIGNED_BYTE,texbuf);
1343 memset(texbuf,0,w*h*3);
1344 // d=dest->bm_data+dx+(dy+i)*dest->bm_rowsize;
1345 d=dest->bm_data+dx+dy*dest->bm_rowsize;
1347 s=texbuf+w*(h-(i+1))*3;
1349 if (s<texbuf){Error("blah1\n");}
1350 if (d<dest->bm_data){Error("blah3\n");}
1351 // d=dest->bm_data+(i*dest->bm_rowsize);
1355 if (s>texbuf+w*h*3-3){Error("blah2\n");}
1356 if (d>dest->bm_data+dest->bm_rowsize*(h+dy)+dx ){Error("blah4\n");}
1357 *d=gr_find_closest_color(s[0]/4,s[1]/4,s[2]/4);
1363 d+=dest->bm_rowsize;
1365 glmprintf((0,"c=%i w*h=%i\n",c,w*h));
1370 bool ogl_ubitblt_copy(int w,int h,int dx,int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest){
1371 #if 0 //just seems to cause a mess.
1372 GLfloat xo,yo;//,xs,ys;
1377 // xo=dx/(float)last_width;
1378 xo=dx/(float)grd_curscreen->sc_w;
1379 // yo=1.0-(dy+h)/(float)last_height;
1380 yo=1.0-(dy+h)/(float)grd_curscreen->sc_h;
1383 OGL_DISABLE(TEXTURE_2D);
1384 glReadBuffer(GL_FRONT);
1385 glRasterPos2f(xo,yo);
1386 // glReadPixels(0,0,w,h,GL_RGB,GL_UNSIGNED_BYTE,texbuf);
1387 glCopyPixels(sx,grd_curscreen->sc_h-(sy+h),w,h,GL_COLOR);
1393 grs_canvas *offscreen_save_canv = NULL, *offscreen_canv = NULL;
1395 void ogl_start_offscreen_render(int x, int y, int w, int h)
1398 Error("ogl_start_offscreen_render: offscreen_canv!=NULL");
1399 offscreen_save_canv = grd_curcanv;
1400 offscreen_canv = gr_create_sub_canvas(grd_curcanv, x, y, w, h);
1401 gr_set_current_canvas(offscreen_canv);
1402 glDrawBuffer(GL_BACK);
1404 void ogl_end_offscreen_render(void)
1408 if (!offscreen_canv)
1409 Error("ogl_end_offscreen_render: no offscreen_canv");
1411 glDrawBuffer(GL_FRONT);
1412 glReadBuffer(GL_BACK);
1413 OGL_DISABLE(TEXTURE_2D);
1415 y = last_height - offscreen_canv->cv_bitmap.bm_y - offscreen_canv->cv_bitmap.bm_h;
1416 glRasterPos2f(offscreen_canv->cv_bitmap.bm_x/(float)last_width, y/(float)last_height);
1417 glCopyPixels(offscreen_canv->cv_bitmap.bm_x, y,
1418 offscreen_canv->cv_bitmap.bm_w,
1419 offscreen_canv->cv_bitmap.bm_h, GL_COLOR);
1421 gr_free_sub_canvas(offscreen_canv);
1422 gr_set_current_canvas(offscreen_save_canv);
1423 offscreen_canv=NULL;
1426 void ogl_start_frame(void){
1427 r_polyc=0;r_tpolyc=0;r_bitmapc=0;r_ubitmapc=0;r_ubitbltc=0;r_upixelc=0;
1428 // gl_badtexture=500;
1430 OGL_VIEWPORT(grd_curcanv->cv_bitmap.bm_x,grd_curcanv->cv_bitmap.bm_y,Canvas_width,Canvas_height);
1431 glClearColor(0.0, 0.0, 0.0, 0.0);
1432 // glEnable(GL_ALPHA_TEST);
1433 // glAlphaFunc(GL_GREATER,0.01);
1434 glShadeModel(GL_SMOOTH);
1435 glMatrixMode(GL_PROJECTION);
1436 glLoadIdentity();//clear matrix
1437 //gluPerspective(90.0,(GLfloat)(grd_curscreen->sc_w*3)/(GLfloat)(grd_curscreen->sc_h*4),1.0,1000000.0);
1438 //gluPerspective(90.0,(GLfloat)(grd_curscreen->sc_w*3)/(GLfloat)(grd_curscreen->sc_h*4),0.01,1000000.0);
1439 gluPerspective(90.0,1.0,0.01,1000000.0);
1440 //gluPerspective(90.0,(GLfloat)(Canvas_width*3)/(GLfloat)(Canvas_height*4),0.01,1000000.0);
1441 // gluPerspective(75.0,(GLfloat)Canvas_width/(GLfloat)Canvas_height,1.0,1000000.0);
1442 glMatrixMode(GL_MODELVIEW);
1443 glLoadIdentity();//clear matrix
1445 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1446 // glDisABLE(DITHER);
1447 // glScalef(1.0,1.0,-1.0);
1448 // glScalef(1.0,1.0,-1.0);
1451 // glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
1452 // OGL_TEXENV(GL_TEXTURE_ENV_MODE,GL_MODULATE);
1453 // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_texmagfilt);
1454 // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_texminfilt);
1455 // OGL_TEXPARAM(GL_TEXTURE_MAG_FILTER,GL_texmagfilt);
1456 // OGL_TEXPARAM(GL_TEXTURE_MIN_FILTER,GL_texminfilt);
1457 // glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1458 // glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1461 void merge_textures_stats(void);
1463 void ogl_end_frame(void){
1464 // OGL_VIEWPORT(grd_curcanv->cv_bitmap.bm_x,grd_curcanv->cv_bitmap.bm_y,);
1465 OGL_VIEWPORT(0,0,grd_curscreen->sc_w,grd_curscreen->sc_h);
1467 // merge_textures_stats();
1468 // ogl_texture_stats();
1470 // glViewport(0,0,grd_curscreen->sc_w,grd_curscreen->sc_h);
1471 glMatrixMode(GL_PROJECTION);
1472 glLoadIdentity();//clear matrix
1473 glOrtho(0.0, 1.0, 0.0, 1.0, -1.0, 1.0);
1474 glMatrixMode(GL_MODELVIEW);
1475 glLoadIdentity();//clear matrix
1476 // glDisABLE(BLEND);
1477 //glDisABLE(ALPHA_TEST);
1478 //gluPerspective(90.0,(GLfloat)(grd_curscreen->sc_w*3)/(GLfloat)(grd_curscreen->sc_h*4),1.0,1000000.0);
1479 // ogl_swap_buffers();//platform specific code
1480 // glClear(GL_COLOR_BUFFER_BIT);
1482 void ogl_swap_buffers(void){
1483 ogl_clean_texture_cache();
1484 if (gr_renderstats){
1485 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);
1486 // 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
1489 ogl_swap_buffers_internal();
1490 glClear(GL_COLOR_BUFFER_BIT);
1493 void ogl_init_shared_palette(void)
1495 #ifdef GL_EXT_paletted_texture
1496 if (ogl_shared_palette_ok)
1500 glEnable(GL_SHARED_TEXTURE_PALETTE_EXT);
1501 //glColorTableEXT(GL_SHARED_TEXTURE_PALETTE_EXT, GL_RGB, 256, GL_RGB, GL_UNSIGNED_BYTE, ogl_pal);
1503 for (i = 0; i < 256; i++)
1507 texbuf[i * 4] = 255;
1508 texbuf[i * 4 + 1] = 255;
1509 texbuf[i * 4 + 2] = 255;
1510 texbuf[i * 4 + 3] = 0;
1515 texbuf[i * 4 + 1] = 0;
1516 texbuf[i * 4 + 2] = 0;
1517 texbuf[i * 4 + 3] = 0;
1521 texbuf[i * 4] = gr_current_pal[i * 3] * 4;
1522 texbuf[i * 4 + 1] = gr_current_pal[i * 3 + 1] * 4;
1523 texbuf[i * 4 + 2] = gr_current_pal[i * 3 + 2] * 4;
1524 texbuf[i * 4 + 3] = 255;
1527 glColorTableEXT(GL_SHARED_TEXTURE_PALETTE_EXT, GL_RGBA, 256, GL_RGBA, GL_UNSIGNED_BYTE, texbuf);
1532 int tex_format_supported(int iformat,int format){
1535 return ogl_intensity4_ok;
1536 case GL_LUMINANCE4_ALPHA4:
1537 return ogl_luminance4_alpha4_ok;
1539 return ogl_rgba2_ok;
1541 if (ogl_gettexlevelparam_ok){
1542 GLint internalFormat;
1543 glTexImage2D(GL_PROXY_TEXTURE_2D, 0, iformat, 64, 64, 0,
1544 format, GL_UNSIGNED_BYTE, texbuf);//NULL?
1545 glGetTexLevelParameteriv(GL_PROXY_TEXTURE_2D, 0,
1546 GL_TEXTURE_INTERNAL_FORMAT,
1548 return (internalFormat==iformat);
1553 //little hack to find the largest or equal multiple of 2 for a given number
1557 for (i = 1; i <= 4096; i *= 2)
1562 //GLubyte texbuf[512*512*4];
1563 GLubyte texbuf[OGLTEXBUFSIZE];
1565 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)
1567 // GLushort *tex=(GLushort *)texp;
1569 if (twidth*theight*4>sizeof(texbuf))//shouldn't happen, descent never uses textures that big.
1570 Error("texture toobig %i %i",twidth,theight);
1573 for (y=0;y<theight;y++){
1574 i=dxo+truewidth*(y+dyo);
1575 for (x=0;x<twidth;x++){
1576 if (x<width && y<height)
1581 for (j = 0; j < data_format; ++j)
1582 (*(texp++)) = data[i * data_format + j];
1589 c = 256; // fill the pad space with transparency (or blackness)
1590 if (c == 254 && (bm_flags & BM_FLAG_SUPER_TRANSPARENT))
1594 case GL_LUMINANCE_ALPHA:
1602 (*(texp++)) = 0; // transparent pixel
1604 case GL_COLOR_INDEX:
1608 Error("ogl_filltexbuf unhandled super-transparent texformat\n");
1612 else if ((c == 255 && (bm_flags & BM_FLAG_TRANSPARENT)) || c == 256)
1618 case GL_LUMINANCE_ALPHA:
1631 (*(texp++))=0;//transparent pixel
1633 case GL_COLOR_INDEX:
1637 Error("ogl_filltexbuf unknown texformat\n");
1642 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. :)
1645 case GL_LUMINANCE_ALPHA:
1650 (*(texp++)) = ogl_pal[c * 3] * 4;
1651 (*(texp++)) = ogl_pal[c * 3 + 1] * 4;
1652 (*(texp++)) = ogl_pal[c * 3 + 2] * 4;
1655 //(*(texp++))=gr_palette[c*3]*4;
1656 //(*(texp++))=gr_palette[c*3+1]*4;
1657 //(*(texp++))=gr_palette[c*3+2]*4;
1658 (*(texp++))=ogl_pal[c*3]*4;
1659 (*(texp++))=ogl_pal[c*3+1]*4;
1660 (*(texp++))=ogl_pal[c*3+2]*4;
1661 (*(texp++))=255;//not transparent
1662 // (*(tex++))=(ogl_pal[c*3]>>1) + ((ogl_pal[c*3+1]>>1)<<5) + ((ogl_pal[c*3+2]>>1)<<10) + (1<<15);
1664 case GL_COLOR_INDEX:
1668 Error("ogl_filltexbuf unknown texformat\n");
1676 int tex_format_verify(ogl_texture *tex){
1677 while (!tex_format_supported(tex->internalformat,tex->format)){
1678 glmprintf((0,"tex format %x not supported",tex->internalformat));
1679 switch (tex->internalformat){
1681 if (ogl_luminance4_alpha4_ok){
1682 tex->internalformat=GL_LUMINANCE4_ALPHA4;
1683 tex->format=GL_LUMINANCE_ALPHA;
1685 }//note how it will fall through here if the statement is false
1686 case GL_LUMINANCE4_ALPHA4:
1688 tex->internalformat=GL_RGBA2;
1689 tex->format=GL_RGBA;
1691 }//note how it will fall through here if the statement is false
1693 #if defined(__APPLE__) && defined(__MACH__)
1694 case GL_RGB8: // Quartz doesn't support RGB only
1696 tex->internalformat = ogl_rgba_internalformat;
1697 tex->format=GL_RGBA;
1700 mprintf((0,"...no tex format to fall back on\n"));
1703 glmprintf((0,"...falling back to %x\n",tex->internalformat));
1707 void tex_set_size1(ogl_texture *tex,int dbits,int bits,int w, int h){
1709 if (tex->tw!=w || tex->th!=h){
1710 u=(tex->w/(float)tex->tw*w) * (tex->h/(float)tex->th*h);
1711 glmprintf((0,"shrunken texture?\n"));
1714 if (bits<=0){//the beta nvidia GLX server. doesn't ever return any bit sizes, so just use some assumptions.
1715 tex->bytes=((float)w*h*dbits)/8.0;
1716 tex->bytesu=((float)u*dbits)/8.0;
1718 tex->bytes=((float)w*h*bits)/8.0;
1719 tex->bytesu=((float)u*bits)/8.0;
1721 glmprintf((0,"tex_set_size1: %ix%i, %ib(%i) %iB\n",w,h,bits,dbits,tex->bytes));
1723 void tex_set_size(ogl_texture *tex){
1726 if (ogl_gettexlevelparam_ok){
1728 glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_WIDTH,&w);
1729 glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_HEIGHT,&h);
1730 glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_LUMINANCE_SIZE,&t);a+=t;
1731 glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_INTENSITY_SIZE,&t);a+=t;
1732 glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_RED_SIZE,&t);a+=t;
1733 glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_GREEN_SIZE,&t);a+=t;
1734 glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_BLUE_SIZE,&t);a+=t;
1735 glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_ALPHA_SIZE,&t);a+=t;
1736 #ifdef GL_EXT_paletted_texture
1737 if (ogl_paletted_texture_ok)
1739 glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INDEX_SIZE_EXT, &t);
1747 switch (tex->format){
1751 case GL_LUMINANCE_ALPHA:
1758 case GL_COLOR_INDEX:
1762 Error("tex_set_size unknown texformat\n");
1765 tex_set_size1(tex,bi,a,w,h);
1767 //loads a palettized bitmap into a ogl RGBA texture.
1768 //Sizes and pads dimensions to multiples of 2 if necessary.
1769 //In theory this could be a problem for repeating textures, but all real
1770 //textures (not sprites, etc) in descent are 64x64, so we are ok.
1771 //stores OpenGL textured id in *texid and u/v values required to get only the real data in *u/*v
1772 void ogl_loadtexture(unsigned char *data, int dxo, int dyo, ogl_texture *tex, int bm_flags, int data_format)
1774 //void ogl_loadtexture(unsigned char * data, int width, int height,int dxo,int dyo, int *texid,float *u,float *v,char domipmap,float prio){
1775 // int internalformat=GL_RGBA;
1776 // int format=GL_RGBA;
1778 tex->tw=pow2ize(tex->w);tex->th=pow2ize(tex->h);//calculate smallest texture size that can accomodate us (must be multiples of 2)
1779 // tex->tw=tex->w;tex->th=tex->h;//feeling lucky?
1781 if(gr_badtexture>0) return;
1783 if (tex_format_verify(tex))
1786 //calculate u/v values that would make the resulting texture correctly sized
1787 tex->u=(float)tex->w/(float)tex->tw;
1788 tex->v=(float)tex->h/(float)tex->th;
1790 #ifdef GL_EXT_paletted_texture
1791 if (ogl_shared_palette_ok && data_format == 0 && (tex->format == GL_RGBA || tex->format == GL_RGB) &&
1792 !(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.
1795 // descent makes palette entries 254 and 255 both do double duty, depending upon the setting of BM_FLAG_SUPER_TRANSPARENT and BM_FLAG_TRANSPARENT.
1796 // 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.)
1797 // We don't handle super transparent textures with ogl yet, so we don't bother checking that here.
1798 int usesthetransparentindexcolor = 0, usesthesupertransparentindexcolor = 0;
1800 if (!(bm_flags & BM_FLAG_SUPER_TRANSPARENT))
1804 for (i = 0; i < tex->w * tex->h; ++i)
1806 usesthesupertransparentindexcolor += 1;
1808 if (!(bm_flags & BM_FLAG_TRANSPARENT))
1812 for (i=0; i < tex->w * tex->h; ++i)
1814 usesthetransparentindexcolor += 1;
1816 if (!usesthetransparentindexcolor && !usesthesupertransparentindexcolor)
1818 tex->internalformat = GL_COLOR_INDEX8_EXT;
1819 tex->format = GL_COLOR_INDEX;
1822 // printf("bm data=%p w=%i h=%i transparent:%i supertrans:%i\n", data, tex->w, tex->h, usesthetransparentindexcolor, usesthesupertransparentindexcolor);
1826 // if (width!=twidth || height!=theight)
1827 // glmprintf((0,"sizing %ix%i texture up to %ix%i\n",width,height,twidth,theight));
1828 ogl_filltexbuf(data, texbuf, tex->lw, tex->w, tex->h, dxo, dyo, tex->tw, tex->th, tex->format, bm_flags, data_format);
1830 // Generate OpenGL texture IDs.
1831 glGenTextures(1, &tex->handle);
1834 glPrioritizeTextures(1,&tex->handle,&tex->prio);
1836 // Give our data to OpenGL.
1838 OGL_BINDTEXTURE(tex->handle);
1840 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
1842 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_texmagfilt);
1843 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_texminfilt);
1844 if (ogl_ext_texture_filter_anisotropic_ok && GL_texanisofilt)
1845 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, GL_texanisofilt);
1849 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1850 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1852 // domipmap=0;//mipmaps aren't used in GL_NEAREST anyway, and making the mipmaps is pretty slow
1853 //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.
1855 if (tex->wantmip && GL_needmipmaps)
1856 gluBuild2DMipmaps( GL_TEXTURE_2D, tex->internalformat, tex->tw,
1857 tex->th, tex->format, GL_UNSIGNED_BYTE, texbuf);
1859 glTexImage2D(GL_TEXTURE_2D, 0, tex->internalformat,
1860 tex->tw, tex->th, 0, tex->format, // RGBA textures.
1861 GL_UNSIGNED_BYTE, // imageData is a GLubyte pointer.
1867 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));
1871 unsigned char decodebuf[1024*1024];
1873 void ogl_loadbmtexture_f(grs_bitmap *bm, int flags)
1880 while (bm->bm_parent)
1882 if (bm->gltexture && bm->gltexture->handle > 0)
1886 if ((bitmapname = piggy_game_bitmap_name(bm)))
1891 sprintf(filename, "textures/%s.png", bitmapname);
1892 if (read_png(filename, &pdata))
1894 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);
1895 if (pdata.depth == 8 && pdata.color)
1897 if (bm->gltexture == NULL)
1898 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));
1899 ogl_loadtexture(pdata.data, 0, 0, bm->gltexture, bm->bm_flags, pdata.paletted ? 0 : pdata.channels);
1902 free(pdata.palette);
1907 printf("%s: unsupported texture format: must be rgb, rgba, or paletted, and depth 8\n", filename);
1910 free(pdata.palette);
1915 if (bm->gltexture == NULL){
1916 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));
1919 if (bm->gltexture->handle>0)
1921 if (bm->gltexture->w==0){
1922 bm->gltexture->lw=bm->bm_w;
1923 bm->gltexture->w=bm->bm_w;
1924 bm->gltexture->h=bm->bm_h;
1927 if (bm->bm_flags & BM_FLAG_RLE){
1928 unsigned char * dbits;
1929 unsigned char * sbits;
1933 if (bm->bm_flags & BM_FLAG_RLE_BIG)
1936 sbits = &bm->bm_data[4 + (bm->bm_h * data_offset)];
1939 for (i=0; i < bm->bm_h; i++ ) {
1940 gr_rle_decode(sbits,dbits);
1941 if ( bm->bm_flags & BM_FLAG_RLE_BIG )
1942 sbits += (int)INTEL_SHORT(*((short *)&(bm->bm_data[4+(i*data_offset)])));
1944 sbits += (int)bm->bm_data[4+i];
1949 ogl_loadtexture(buf, 0, 0, bm->gltexture, bm->bm_flags, 0);
1952 void ogl_loadbmtexture(grs_bitmap *bm)
1954 ogl_loadbmtexture_f(bm, OGL_FLAG_MIPMAP);
1957 void ogl_freetexture(ogl_texture *gltexture)
1959 if (gltexture->handle>0) {
1961 glmprintf((0,"ogl_freetexture(%p):%i (last rend %is) (%i left)\n",gltexture,gltexture->handle,(GameTime-gltexture->lastrend)/f1_0,r_texcount));
1962 glDeleteTextures( 1, &gltexture->handle );
1963 // gltexture->handle=0;
1964 ogl_reset_texture(gltexture);
1967 void ogl_freebmtexture(grs_bitmap *bm){
1969 ogl_freetexture(bm->gltexture);
1972 // glmprintf((0,"ogl_freebmtexture(%p,%p):%i (%i left)\n",bm->bm_data,&bm->gltexture,bm->gltexture,r_texcount));
1973 // glDeleteTextures( 1, &bm->gltexture );
1974 // bm->gltexture=-1;
1979 bool ogl_ubitmapm_cs(int x, int y, int dw, int dh, grs_bitmap *bm, int c, int scale, int orient)
1981 GLfloat xo, yo, xf, yf;
1982 GLfloat u1, u2, v1, v2;
1986 x += grd_curcanv->cv_bitmap.bm_x;
1987 y += grd_curcanv->cv_bitmap.bm_y;
1988 xo = x / (float)last_width;
1989 xf = (bm->bm_w + x) / (float)last_width;
1990 yo = 1.0 - y / (float)last_height;
1991 yf = 1.0 - (bm->bm_h + y) / (float)last_height;
1994 dw = grd_curcanv->cv_bitmap.bm_w;
1998 dh = grd_curcanv->cv_bitmap.bm_h;
2008 x += grd_curcanv->cv_bitmap.bm_y;
2009 y += grd_curcanv->cv_bitmap.bm_x;
2011 x += grd_curcanv->cv_bitmap.bm_x;
2012 y += grd_curcanv->cv_bitmap.bm_y;
2015 a = (double) grd_curscreen->sc_w / (double) grd_curscreen->sc_h;
2016 h = (double) scale / (double) F1_0;
2018 xo = x / ((double) last_width * h);
2019 xf = (dw + x) / ((double) last_width * h);
2020 yo = 1.0 - y / ((double) last_height * h);
2021 yf = 1.0 - (dh + y) / ((double) last_height * h);
2023 OGL_ENABLE(TEXTURE_2D);
2025 ogl_texwrap(bm->gltexture,GL_CLAMP);
2027 if (bm->bm_x == 0) {
2029 if (bm->bm_w == bm->gltexture->w)
2030 u2 = bm->gltexture->u;
2032 u2 = (bm->bm_w + bm->bm_x) / (float)bm->gltexture->tw;
2034 u1 = bm->bm_x / (float)bm->gltexture->tw;
2035 u2 = (bm->bm_w + bm->bm_x) / (float)bm->gltexture->tw;
2038 if (bm->bm_y == 0) {
2040 if (bm->bm_h == bm->gltexture->h)
2041 v2 = bm->gltexture->v;
2043 v2 = (bm->bm_h + bm->bm_y) / (float)bm->gltexture->th;
2045 v1 = bm->bm_y / (float)bm->gltexture->th;
2046 v2 = (bm->bm_h + bm->bm_y) / (float)bm->gltexture->th;
2051 glColor3f(1.0, 1.0, 1.0);
2053 glColor3f(CPAL2Tr(c), CPAL2Tg(c), CPAL2Tb(c));
2054 glTexCoord2f(u1, v1); glVertex2f(xo, yo);
2055 glTexCoord2f(u2, v1); glVertex2f(xf, yo);
2056 glTexCoord2f(u2, v2); glVertex2f(xf, yf);
2057 glTexCoord2f(u1, v2); glVertex2f(xo, yf);
2058 #ifndef _WIN32 // ZICO - hack
2059 glActiveTexture(GL_TEXTURE0_ARB);