SHOW:
|
|
- or go back to the newest paste.
1 | #include "Draw.h" | |
2 | - | #include <stdio.h> |
2 | + | ///vars to add to structs |
3 | - | #include <stdlib.h> |
3 | + | struct OGL_Texture{ |
4 | - | #include <cstring> |
4 | + | float bw,bh;//blit width/height if non pwr 2 textures |
5 | - | using namespace std; |
5 | + | }; |
6 | struct OGL_Surface : OGL_Texture{ | |
7 | float bw,bh; | |
8 | }; | |
9 | ||
10 | - | //OGL Texture// |
10 | + | ///Draw Funcs to replace (also replace "GL_TEXTURE_RECTANGLE_NV" with "GL_TEXTURE_2D") |
11 | bool IsPowerOfTwo(uint32_t x) | |
12 | - | OGL_Texture::OGL_Texture(){ |
12 | + | |
13 | - | w=h=0; |
13 | + | return ((x & (x - 1)) == 0); |
14 | - | texture_generated = false; |
14 | + | |
15 | - | Texture_ID = 0; |
15 | + | int HighestBit(uint32_t x) |
16 | { | |
17 | - | OGL_Texture::~OGL_Texture(){ |
17 | + | if (IsPowerOfTwo(x)){return x;} |
18 | - | if (Texture_ID){glDeleteTextures(1,&Texture_ID);}//0 is not a valid texture id |
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 | - | glEnable(GL_TEXTURE_RECTANGLE_NV); |
32 | + | bool todelete = false; |
33 | - | glBindTexture(GL_TEXTURE_RECTANGLE_NV, Texture_ID); |
33 | + | if (!(IsPowerOfTwo(w) && IsPowerOfTwo(h))){ |
34 | uint32_t new_w = HighestBit(w); | |
35 | - | glTexImage2D(GL_TEXTURE_RECTANGLE_NV, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, PixData); |
35 | + | uint32_t new_h = HighestBit(h); |
36 | - | glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |
36 | + | NewPixData = new uint8_t[new_w*new_h*4]; |
37 | - | glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
37 | + | memset(NewPixData,255, new_w*new_h*4); |
38 | - | glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
38 | + | uint32_t pos1 = 0; |
39 | - | glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
39 | + | uint32_t pos2 = 0; |
40 | for (uint32_t y = 0; y<h; y++){ | |
41 | for (uint32_t x = 0; x<w; x++){ | |
42 | - | glDisable(GL_TEXTURE_RECTANGLE_NV); |
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 | - | OGL_Surface::OGL_Surface(){ |
50 | + | |
51 | - | texture_generated = false; |
51 | + | width= new_w; |
52 | - | bpp=4; |
52 | + | height= new_h; |
53 | - | w=h=0; |
53 | + | bw = float(w)/float(new_w); |
54 | - | PixData = nullptr; |
54 | + | bh = float(h)/float(new_h); |
55 | todelete = true; | |
56 | - | OGL_Surface::~OGL_Surface(){ |
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 | - | void OGL_Surface::Clear_Surface(uint8_t r, uint8_t g, uint8_t b, uint8_t a){ |
76 | + | |
77 | - | if (r == g && g == b && bpp==3){ |
77 | + | |
78 | - | memset(PixData, r, w*h*bpp); |
78 | + | |
79 | void OGL_Surface::Create_Surface(uint16_t set_w,uint16_t set_h, char set_bpp){ | |
80 | - | else if (r == g && g == b && b == a && bpp==4){ |
80 | + | |
81 | - | memset(PixData, r, w*h*bpp); |
81 | + | |
82 | // if surface already exists and width or height change delete old texture | |
83 | - | else{ |
83 | + | |
84 | - | unsigned int pos = 0; |
84 | + | |
85 | - | while (pos<w*h*bpp){ |
85 | + | |
86 | - | PixData[pos++] = r; |
86 | + | |
87 | - | PixData[pos++] = g; |
87 | + | |
88 | - | PixData[pos++] = b; |
88 | + | |
89 | - | if(bpp==4){PixData[pos++] = a;} |
89 | + | |
90 | h = set_h; | |
91 | bpp = set_bpp; | |
92 | PixData = new uint8_t[w*h*bpp]; | |
93 | - | void OGL_Surface::Set_Surface_AlphaKey(uint8_t r, uint8_t g, uint8_t b) |
93 | + | |
94 | if (!(IsPowerOfTwo(w) && IsPowerOfTwo(h))){printf("WARNING: non pow two surface, may be slow\n");} | |
95 | - | if(bpp!=4){printf("trying to set alphakey on bpp that does not support alpha\n");return;} |
95 | + | |
96 | - | int pos = 0; |
96 | + | |
97 | - | for (unsigned int y = 0; y<h; y++){ |
97 | + | |
98 | - | for (unsigned int x = 0; x<w; x++){ |
98 | + | |
99 | - | if ((PixData[pos]==r) && (PixData[pos+1]==b) && (PixData[pos+2] == b)){ |
99 | + | |
100 | - | PixData[pos+3]= 0;//if colour = alphakey set alpha channel to 0 |
100 | + | |
101 | uint8_t *NewPixData = PixData; | |
102 | - | pos+=4; |
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 | - | glEnable(GL_TEXTURE_RECTANGLE_NV); |
116 | + | pos1+=4; |
117 | - | glBindTexture(GL_TEXTURE_RECTANGLE_NV, Texture_ID); |
117 | + | pos2+=4; |
118 | } | |
119 | pos1+=(new_w-w)*4; | |
120 | } | |
121 | width= new_w; | |
122 | height= new_h; | |
123 | - | case 3: glTexImage2D(GL_TEXTURE_RECTANGLE_NV, 0, GL_RGBA8, width, height, 0, GL_BGR, GL_UNSIGNED_BYTE, PixData); break; |
123 | + | bw = w/new_w; |
124 | - | case 4: glTexImage2D(GL_TEXTURE_RECTANGLE_NV, 0, GL_RGBA8, width, height, 0, GL_BGRA,GL_UNSIGNED_BYTE, PixData); break; |
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 | - | case 3: glTexSubImage2D(GL_TEXTURE_RECTANGLE_NV, 0, 0, 0, width, height, GL_BGR, GL_UNSIGNED_BYTE, PixData); break; |
132 | + | glEnable(GL_TEXTURE_2D); |
133 | - | case 4: glTexSubImage2D(GL_TEXTURE_RECTANGLE_NV, 0, 0, 0, width, height, GL_BGRA,GL_UNSIGNED_BYTE, PixData); break; |
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 | - | glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |
136 | + | |
137 | - | glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
137 | + | |
138 | - | glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
138 | + | |
139 | - | glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
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 | - | glDisable(GL_TEXTURE_RECTANGLE_NV); |
142 | + | |
143 | //glTexSubImage2D only modifies pixel data within the texture. | |
144 | //do this when pixels need to be updated | |
145 | else{ | |
146 | - | OGL_Texture *Texture_Cast(OGL_Surface *Surface) |
146 | + | |
147 | //2d texture, level of detail, xoffset,yoffset, w,h, byte order, data format, data | |
148 | - | OGL_Texture *Texture = static_cast<OGL_Texture*>(Surface); |
148 | + | case 3: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_BGR, GL_UNSIGNED_BYTE, NewPixData); break; |
149 | - | Texture->w = Surface->w; |
149 | + | case 4: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_BGRA,GL_UNSIGNED_BYTE, NewPixData); break; |
150 | - | Texture->h = Surface->h; |
150 | + | |
151 | - | return Texture; |
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 | - | glEnable(GL_TEXTURE_RECTANGLE_NV); |
178 | + | |
179 | - | glEnable(GL_BLEND); |
179 | + | |
180 | - | //additive blending - gray + gray = white |
180 | + | |
181 | - | if (options &= IMG_ADD_BLEND){glBlendFunc(GL_SRC_ALPHA, GL_ONE);} |
181 | + | |
182 | - | //regular alpha blending - gray + gray = gray |
182 | + | |
183 | - | else{glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);} |
183 | + | |
184 | - | //blit |
184 | + | |
185 | - | glColor4f(1.0f, 1.0f, 1.0f, alpha); |
185 | + | |
186 | - | glBindTexture(GL_TEXTURE_RECTANGLE_NV, Texture->Texture_ID); |
186 | + | glEnable(GL_TEXTURE_2D); |
187 | - | glBegin(GL_QUADS); |
187 | + | glEnable(GL_BLEND); |
188 | - | glTexCoord2i(0,0); |
188 | + | //additive blending - gray + gray = white |
189 | - | glVertex2i(0, 0); |
189 | + | if (options &= IMG_ADD_BLEND){glBlendFunc(GL_SRC_ALPHA, GL_ONE);} |
190 | - | glTexCoord2i(Texture->w,0); |
190 | + | //regular alpha blending - gray + gray = gray |
191 | - | glVertex2i(Texture->w, 0); |
191 | + | else{glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);} |
192 | - | glTexCoord2i(Texture->w,Texture->h); |
192 | + | //blit |
193 | - | glVertex2i(Texture->w, Texture->h); |
193 | + | glColor4f(1.0f, 1.0f, 1.0f, alpha); |
194 | - | glTexCoord2i(0,Texture->h); |
194 | + | glBindTexture(GL_TEXTURE_2D, Texture->Texture_ID); |
195 | - | glVertex2i(0, Texture->h); |
195 | + | glBegin(GL_QUADS); |
196 | - | glEnd(); |
196 | + | glTexCoord2f(0,0); |
197 | - | glDisable(GL_BLEND); |
197 | + | glVertex2d(0, 0); |
198 | - | glDisable(GL_TEXTURE_RECTANGLE_NV); |
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 | - | glEnable(GL_TEXTURE_RECTANGLE_NV); |
214 | + | tex_coord_x1 *= Texture->bw; |
215 | - | glEnable(GL_BLEND); |
215 | + | tex_coord_y1 *= Texture->bh; |
216 | - | //additive blending - gray + gray = white |
216 | + | tex_coord_x2 *= Texture->bw; |
217 | - | if (options &= IMG_ADD_BLEND){glBlendFunc(GL_SRC_ALPHA, GL_ONE);} |
217 | + | tex_coord_y2 *= Texture->bh; |
218 | - | //regular alpha blending - gray + gray = gray |
218 | + | |
219 | - | else{glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);} |
219 | + | |
220 | - | //blit |
220 | + | |
221 | - | glColor4f(1.0,1.0,1.0,alpha); |
221 | + | |
222 | - | glBindTexture(GL_TEXTURE_RECTANGLE_NV, Texture->Texture_ID); |
222 | + | |
223 | - | glBegin(GL_QUADS); |
223 | + | |
224 | - | glTexCoord2i(sx,sy); |
224 | + | |
225 | - | glVertex2i(0, 0); |
225 | + | |
226 | - | glTexCoord2i(sx+sw,sy); |
226 | + | |
227 | - | glVertex2i(sw, 0); |
227 | + | |
228 | - | glTexCoord2i(sx+sw,sy+sh); |
228 | + | |
229 | - | glVertex2i(sw, sh); |
229 | + | |
230 | - | glTexCoord2i(sx,sy+sh); |
230 | + | glEnable(GL_TEXTURE_2D); |
231 | - | glVertex2i(0, sh); |
231 | + | glEnable(GL_BLEND); |
232 | - | glEnd(); |
232 | + | //additive blending - gray + gray = white |
233 | - | glDisable(GL_BLEND); |
233 | + | if (options &= IMG_ADD_BLEND){glBlendFunc(GL_SRC_ALPHA, GL_ONE);} |
234 | - | glDisable(GL_TEXTURE_RECTANGLE_NV); |
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 | - | ////////// |
238 | + | glBindTexture(GL_TEXTURE_2D, Texture->Texture_ID); |
239 | - | //COLOUR// |
239 | + | glBegin(GL_QUADS); |
240 | - | ////////// |
240 | + | glTexCoord2f(tex_coord_x1,tex_coord_y1); |
241 | - | uint32_t make_col(uint8_t r, uint8_t g, uint8_t b, uint8_t a){ |
241 | + | glVertex2d(0, 0); |
242 | - | uint32_t col = 0; |
242 | + | glTexCoord2f(tex_coord_x2,tex_coord_y1); |
243 | - | col |= r; |
243 | + | glVertex2d(sw, 0); |
244 | - | col |= uint32_t(g)<<8; |
244 | + | glTexCoord2f(tex_coord_x2,tex_coord_y2); |
245 | - | col |= uint32_t(b)<<16; |
245 | + | glVertex2d(sw, sh); |
246 | - | col |= uint32_t(a)<<24; |
246 | + | glTexCoord2f(tex_coord_x1,tex_coord_y2); |
247 | - | //printf("%#X, %d,%d,%d\n", col,r,g,b); |
247 | + | glVertex2d(0, sh); |
248 | - | return col; |
248 | + | glEnd(); |
249 | glDisable(GL_BLEND); | |
250 | glDisable(GL_TEXTURE_2D); | |
251 | - | uint32_t make_col(uint8_t r, uint8_t g, uint8_t b){ |
251 | + | |
252 | - | return make_col(r,g,b,255); |
252 | + |