1. #include "Draw.h"
  2. ///vars to add to structs
  3. struct OGL_Texture{
  4.     float bw,bh;//blit width/height if non pwr 2 textures
  5. };
  6. struct OGL_Surface : OGL_Texture{
  7.     float bw,bh;
  8. };
  9.  
  10. ///Draw Funcs to replace (also replace "GL_TEXTURE_RECTANGLE_NV" with "GL_TEXTURE_2D")
  11. bool IsPowerOfTwo(uint32_t x)
  12. {
  13.     return ((x & (x - 1)) == 0);
  14. }
  15. int HighestBit(uint32_t x)
  16. {
  17.     if (IsPowerOfTwo(x)){return x;}
  18.     uint32_t y = 1<<31;
  19.     while (y>x){y=y>>1;}
  20.     return y<<1;
  21. }
  22. void OGL_Texture::gen_texture(uint16_t width, uint16_t height, uint8_t *PixData){
  23.     if (width==0 || height==0){printf("ERROR! WIDTH OR HEIGHT OF TEXTURE == 0"); exit(1);}
  24.     //delete old texture if existing
  25.     if (texture_generated && Texture_ID){
  26.         glDeleteTextures(1,&Texture_ID);
  27.     }
  28.     //Power of two texture support
  29.     w = width;
  30.     h = height;
  31.     uint8_t *NewPixData = PixData;
  32.     bool todelete = false;
  33.     if (!(IsPowerOfTwo(w) && IsPowerOfTwo(h))){
  34.         uint32_t new_w = HighestBit(w);
  35.         uint32_t new_h = HighestBit(h);
  36.         NewPixData = new uint8_t[new_w*new_h*4];
  37.         memset(NewPixData,255, new_w*new_h*4);
  38.         uint32_t pos1 = 0;
  39.         uint32_t pos2 = 0;
  40.         for (uint32_t y = 0; y<h; y++){
  41.             for (uint32_t x = 0; x<w; x++){
  42.                 NewPixData[pos1]  = PixData[pos2];
  43.                 NewPixData[pos1+1]= PixData[pos2+1];
  44.                 NewPixData[pos1+2]= PixData[pos2+2];
  45.                 NewPixData[pos1+3]= PixData[pos2+3];
  46.                 pos1+=4;
  47.                 pos2+=4;
  48.             }
  49.             pos1+=(new_w-w)*4;
  50.         }
  51.         width= new_w;
  52.         height= new_h;
  53.         bw = float(w)/float(new_w);
  54.         bh = float(h)/float(new_h);
  55.         todelete = true;
  56.     }
  57.     //generate texture
  58.     glGenTextures(1,&Texture_ID);
  59.     if (Texture_ID==0){printf("ERROR IN TEXTURE GENERATION! NO DEVICE CONTEXT?"); exit(1);}
  60.     glEnable(GL_TEXTURE_2D);
  61.         glBindTexture(GL_TEXTURE_2D, Texture_ID);
  62.         //2d texture, level of detail, number of components (3=rgb), w,h, border, byte order, data format, data
  63.         glTexImage2D(GL_TEXTURE_2D, 0,GL_RGBA8, width, height, 0, GL_BGRA,GL_UNSIGNED_BYTE, NewPixData);
  64.         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  65.         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  66.         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  67.         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  68.         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
  69.         glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE);
  70.     glDisable(GL_TEXTURE_2D);
  71.     texture_generated = true;
  72.     //cleanup
  73.     if (todelete){delete [] NewPixData;}
  74. }
  75.  
  76. ///////////////
  77. //OGL Surface//
  78. ///////////////
  79. void OGL_Surface::Create_Surface(uint16_t set_w,uint16_t set_h, char set_bpp){
  80.     if (set_bpp==24){bpp=3;}
  81.     if (set_bpp==32){bpp=4;}
  82.     // if surface already exists and width or height change delete old texture
  83.     if (texture_generated && (w != set_w || h != set_h)){
  84.         glDeleteTextures(1,&Texture_ID);
  85.         texture_generated = false;
  86.     }
  87.     // if surface already exists delete old data
  88.     if (PixData != nullptr) {delete [] PixData;}
  89.     w = set_w;
  90.     h = set_h;
  91.     bpp = set_bpp;
  92.     PixData = new uint8_t[w*h*bpp];
  93.     memset(PixData,255, w*h*bpp);
  94.     if (!(IsPowerOfTwo(w) && IsPowerOfTwo(h))){printf("WARNING: non pow two surface, may be slow\n");}
  95. }
  96. void OGL_Surface::gen_texture(){
  97.     if (w==0 || h==0){printf("ERROR! WIDTH OR HEIGHT OF SURFACE == 0"); exit(1);}
  98.     //Power of two texture support
  99.     uint32_t width = w;
  100.     uint32_t height= h;
  101.     uint8_t *NewPixData = PixData;
  102.     bool todelete = false;
  103.     if (!(IsPowerOfTwo(w) && IsPowerOfTwo(h))){
  104.         uint32_t new_w = HighestBit(w);
  105.         uint32_t new_h = HighestBit(h);
  106.         NewPixData = new uint8_t[new_w*new_h*4];
  107.         memset(NewPixData,255, new_w*new_h*4);
  108.         uint32_t pos1 = 0;
  109.         uint32_t pos2 = 0;
  110.         for (uint32_t y = 0; y<h; y++){
  111.             for (uint32_t x = 0; x<w; x++){
  112.                 NewPixData[pos1]  = PixData[pos2];
  113.                 NewPixData[pos1+1]= PixData[pos2+1];
  114.                 NewPixData[pos1+2]= PixData[pos2+2];
  115.                 NewPixData[pos1+3]= PixData[pos2+3];
  116.                 pos1+=4;
  117.                 pos2+=4;
  118.             }
  119.             pos1+=(new_w-w)*4;
  120.         }
  121.         width= new_w;
  122.         height= new_h;
  123.         bw = w/new_w;
  124.         bh = h/new_h;
  125.         todelete = true;
  126.     }
  127.     //only generate a texture once
  128.     if (!texture_generated){
  129.         glGenTextures(1,&Texture_ID);
  130.         if (Texture_ID==0){printf("ERROR IN TEXTURE GENERATION! NO DEVICE CONTEXT?"); exit(1);}
  131.     }
  132.     glEnable(GL_TEXTURE_2D);
  133.         glBindTexture(GL_TEXTURE_2D, Texture_ID);
  134.         //glTexImage2D respecifies the entire texture, changing its size, deleting the previous data etc.
  135.         //only do this if texture doesn't exist or if w/h change
  136.         if (!texture_generated){
  137.             switch (bpp){
  138.             //2d texture, level of detail, number of components (3=rgb), w,h, border, byte order, data format, data
  139.                 case 3: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_BGR, GL_UNSIGNED_BYTE, NewPixData); break;
  140.                 case 4: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_BGRA,GL_UNSIGNED_BYTE, NewPixData); break;
  141.             }
  142.         }
  143.         //glTexSubImage2D only modifies pixel data within the texture.
  144.         //do this when pixels need to be updated
  145.         else{
  146.             switch (bpp){
  147.                 //2d texture, level of detail, xoffset,yoffset, w,h,  byte order, data format, data
  148.                 case 3: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_BGR, GL_UNSIGNED_BYTE, NewPixData); break;
  149.                 case 4: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_BGRA,GL_UNSIGNED_BYTE, NewPixData); break;
  150.             }
  151.         }
  152.         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  153.         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  154.         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  155.         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  156.         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
  157.         glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE);
  158.     glDisable(GL_TEXTURE_2D);
  159.     texture_generated = true;
  160.     //cleanup
  161.     if (todelete){delete [] NewPixData;}
  162. }
  163. //BLIT//
  164. ////////
  165. //glBlendFunc(source_blend, dst_blend)
  166. //GL_ZERO                       colour is ignored
  167. //GL_ONE                        full colour is taken into addition
  168. //GL_(DST/SRC)_COLOR            colour is multiplied by (DST/SRC) color
  169. //GL_ONE_MINUS_(DST/SRC)_COLOR  colour is multiplied by inverted (DST/SRC) color
  170. //GL_(DST/SRC)_ALPHA            colour is multiplied by (DST/SRC) alpha value
  171. //GL_ONE_MINUS_(DST/SRC)_ALPHA  colour is multiplied by inverted (DST/SRC) alpha value
  172. //overall colour (GL_SRC_ALPHA, GL_ONE) -addative- = (r1*a1,g1*a1,b1*a1)+(r2,g2,b2)
  173. void DrawImage(OGL_Texture *Texture, int dx, int dy, float rot,float scale_x,float scale_y,float alpha,int options){
  174.     if (options & IMG_HFLIP){dx+=Texture->w; scale_x=-1;}
  175.     if (options & IMG_VFLIP){dy+=Texture->h; scale_y=-1;}
  176.     glLoadIdentity();
  177.     glTranslatef(dx, dy, 0.0);
  178.     if (scale_x!=1 && scale_y!=1){glScaled(scale_x, scale_y, 0);}
  179.     if (rot!=0){
  180.         int tmpw = Texture->w/2;
  181.         int tmph = Texture->h/2;
  182.         glTranslatef(tmpw, tmph, 0.0);
  183.         glRotatef(rot, 0, 0, 1.0);
  184.         glTranslatef(-tmpw, -tmph, 0.0);
  185.     }
  186.     glEnable(GL_TEXTURE_2D);
  187.     glEnable(GL_BLEND);
  188.         //additive blending - gray + gray = white
  189.         if (options &= IMG_ADD_BLEND){glBlendFunc(GL_SRC_ALPHA, GL_ONE);}
  190.         //regular alpha blending - gray + gray = gray
  191.         else{glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);}
  192.         //blit
  193.         glColor4f(1.0f, 1.0f, 1.0f, alpha);
  194.         glBindTexture(GL_TEXTURE_2D, Texture->Texture_ID);
  195.         glBegin(GL_QUADS);
  196.             glTexCoord2f(0,0);
  197.             glVertex2d(0, 0);
  198.             glTexCoord2f(Texture->bw,0);
  199.             glVertex2d(Texture->w, 0);
  200.             glTexCoord2f(Texture->bw,Texture->bh);
  201.             glVertex2d(Texture->w, Texture->h);
  202.             glTexCoord2f(0,Texture->bh);
  203.             glVertex2d(0, Texture->h);
  204.         glEnd();
  205.     glDisable(GL_BLEND);
  206.     glDisable(GL_TEXTURE_2D);
  207.     glLoadIdentity();
  208. }
  209. void DrawSubImage(OGL_Texture *Texture, int sx, int sy, int sw, int sh, int dx, int dy, float rot,float scale_x,float scale_y,float alpha,int options){
  210.     float tex_coord_x1 = (float)sx/(float)Texture->w;
  211.     float tex_coord_y1 = (float)sy/(float)Texture->h;
  212.     float tex_coord_x2 = tex_coord_x1+((float)sw/(float)Texture->w);
  213.     float tex_coord_y2 = tex_coord_y1+((float)sh/(float)Texture->h);
  214.     tex_coord_x1 *= Texture->bw;
  215.     tex_coord_y1 *= Texture->bh;
  216.     tex_coord_x2 *= Texture->bw;
  217.     tex_coord_y2 *= Texture->bh;
  218.     if (options & IMG_HFLIP){dx+=Texture->w; scale_x=-1;}
  219.     if (options & IMG_VFLIP){dy+=Texture->h; scale_y=-1;}
  220.     glLoadIdentity();
  221.     glTranslatef(dx, dy, 0.0);
  222.     if (scale_x!=1 && scale_y!=1){glScaled(scale_x, scale_y, 0);}
  223.     if (rot!=0){
  224.         int tmpw = Texture->w/2;
  225.         int tmph = Texture->h/2;
  226.         glTranslatef(tmpw, tmph, 0.0);
  227.         glRotatef(rot, 0, 0, 1.0);
  228.         glTranslatef(-tmpw, -tmph, 0.0);
  229.     }
  230.     glEnable(GL_TEXTURE_2D);
  231.     glEnable(GL_BLEND);
  232.         //additive blending - gray + gray = white
  233.         if (options &= IMG_ADD_BLEND){glBlendFunc(GL_SRC_ALPHA, GL_ONE);}
  234.         //regular alpha blending - gray + gray = gray
  235.         else{glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);}
  236.         //blit
  237.         glColor4f(1.0,1.0,1.0,alpha);
  238.         glBindTexture(GL_TEXTURE_2D, Texture->Texture_ID);
  239.         glBegin(GL_QUADS);
  240.             glTexCoord2f(tex_coord_x1,tex_coord_y1);
  241.             glVertex2d(0, 0);
  242.             glTexCoord2f(tex_coord_x2,tex_coord_y1);
  243.             glVertex2d(sw, 0);
  244.             glTexCoord2f(tex_coord_x2,tex_coord_y2);
  245.             glVertex2d(sw, sh);
  246.             glTexCoord2f(tex_coord_x1,tex_coord_y2);
  247.             glVertex2d(0, sh);
  248.         glEnd();
  249.     glDisable(GL_BLEND);
  250.     glDisable(GL_TEXTURE_2D);
  251.     glLoadIdentity();
  252. }