1 #ifndef polymost_h_
2 # define polymost_h_
3 
4 #ifdef USE_OPENGL
5 
6 #include "baselayer.h"  // glinfo
7 #include "glad/glad.h"
8 #include "hightile.h"
9 
10 #ifdef __cplusplus
11 extern "C" {
12 #endif
13 
14 typedef struct { uint8_t r, g, b, a; } coltype;
15 typedef struct { float r, g, b, a; } coltypef;
16 
17 extern int32_t rendmode;
18 extern float gtang;
19 extern int polymost2d;
20 extern double gxyaspect;
21 extern float grhalfxdown10x;
22 extern float gcosang, gsinang, gcosang2, gsinang2;
23 extern float gchang, gshang, gctang, gstang, gvisibility;
24 extern float gvrcorrection;
25 
26 struct glfiltermodes {
27     const char *name;
28     int32_t min,mag;
29 };
30 #define NUMGLFILTERMODES 6
31 extern struct glfiltermodes glfiltermodes[NUMGLFILTERMODES];
32 
33 extern void Polymost_prepare_loadboard(void);
34 
35 void polymost_outputGLDebugMessage(uint8_t severity, const char* format, ...);
36 
37 //void phex(char v, char *s);
38 void polymost_setuptexture(const int32_t dameth, int filter);
39 void uploadtexture(int32_t doalloc, vec2_t siz, int32_t texfmt, coltype *pic, vec2_t tsiz, int32_t dameth);
40 void uploadtextureindexed(int32_t doalloc, vec2_t offset, vec2_t siz, intptr_t tile);
41 void uploadbasepalette(int32_t basepalnum);
42 void uploadpalswap(int32_t palookupnum);
43 void polymost_drawsprite(int32_t snum);
44 void polymost_drawmaskwall(int32_t damaskwallcnt);
45 void polymost_dorotatesprite(int32_t sx, int32_t sy, int32_t z, int16_t a, int16_t picnum,
46                              int8_t dashade, char dapalnum, int32_t dastat, uint8_t daalpha, uint8_t dablend, int32_t cx1, int32_t cy1, int32_t cx2, int32_t cy2, int32_t uniqid);
47 void polymost_fillpolygon(int32_t npoints);
48 void polymost_initosdfuncs(void);
49 void polymost_drawrooms(void);
50 void polymost_prepareMirror(int32_t dax, int32_t day, int32_t daz, fix16_t daang, fix16_t dahoriz, int16_t mirrorWall);
51 void polymost_completeMirror();
52 
53 int32_t polymost_maskWallHasTranslucency(uwalltype const * const wall);
54 int32_t polymost_spriteHasTranslucency(tspritetype const * const tspr);
55 int32_t polymost_spriteIsModelOrVoxel(tspritetype const * const tspr);
56 
57 void polymost_resetVertexPointers(void);
58 void polymost_disableProgram(void);
59 void polymost_resetProgram(void);
60 void polymost_setTexturePosSize(vec4f_t const &texturePosSize);
61 void polymost_setHalfTexelSize(vec2f_t const &halfTexelSize);
62 char polymost_getClamp();
63 void polymost_setClamp(char clamp);
64 void polymost_setVisibility(float visibility);
65 void polymost_setFogEnabled(char fogEnabled);
66 void polymost_useColorOnly(char useColorOnly);
67 void polymost_usePaletteIndexing(char usePaletteIndexing);
68 void polymost_useDetailMapping(char useDetailMapping);
69 void polymost_useGlowMapping(char useGlowMapping);
70 void polymost_activeTexture(GLenum texture);
71 void polymost_bindTexture(GLenum target, uint32_t textureID);
72 void polymost_updatePalette(void);
73 void polymost_useShaderProgram(uint32_t shaderID);
74 GLuint polymost2_compileShader(GLenum shaderType, const char* const source, int* pLength = nullptr);
75 
76 float* multiplyMatrix4f(float m0[4*4], const float m1[4*4]);
77 
78 //POGOTODO: these wrappers won't be needed down the line -- remove them once proper draw call organization is finished
79 #undef glActiveTexture
80 #undef glBindTexture
81 #define glActiveTexture polymost_activeTexture
82 #define glBindTexture polymost_bindTexture
83 
84 void polymost_glinit(void);
85 void polymost_glreset(void);
86 
87 void polymost_init(void);
88 
89 enum {
90     INVALIDATE_ALL,
91     INVALIDATE_ART,
92     INVALIDATE_ALL_NON_INDEXED,
93     INVALIDATE_ART_NON_INDEXED
94 };
95 
96 void gltexinvalidate(int32_t dapicnum, int32_t dapalnum, int32_t dameth);
97 void gltexinvalidatetype(int32_t type);
98 int32_t polymost_printtext256(int32_t xpos, int32_t ypos, int16_t col, int16_t backcol, const char *name, char fontsize);
99 
100 extern float curpolygonoffset;
101 
102 extern float shadescale;
103 extern int32_t shadescale_unbounded;
104 extern uint8_t alphahackarray[MAXTILES];
105 
106 extern int32_t r_usenewshading;
107 extern int32_t r_usetileshades;
108 extern int32_t r_npotwallmode;
109 extern int32_t r_brightnesshack;
110 extern int32_t polymostcenterhoriz;
111 
112 extern int16_t globalpicnum;
113 
114 extern float fogfactor[MAXPALOOKUPS];
115 
116 // Compare with polymer_eligible_for_artmap()
eligible_for_tileshades(int32_t const picnum,int32_t const pal)117 static FORCE_INLINE int32_t eligible_for_tileshades(int32_t const picnum, int32_t const pal)
118 {
119     return !usehightile || !hicfindsubst(picnum, pal, hictinting[pal].f & HICTINT_ALWAYSUSEART);
120 }
121 
polymost_usetileshades(void)122 static FORCE_INLINE int polymost_usetileshades(void)
123 {
124     return r_usetileshades && !(globalflags & GLOBAL_NO_GL_TILESHADES);
125 }
126 
getshadefactor(int32_t const shade,int32_t const pal)127 static inline float getshadefactor(int32_t const shade, int32_t const pal)
128 {
129     // 8-bit tiles, i.e. non-hightiles and non-models, don't get additional
130     // glColor() shading with r_usetileshades!
131     if (videoGetRenderMode() == REND_POLYMOST && polymost_usetileshades() && eligible_for_tileshades(globalpicnum, globalpal))
132         return 1.f;
133 
134     float const fshade = fogfactor[pal] != 0.f ? (float)shade / fogfactor[pal] : 0.f;
135 
136     if (r_usenewshading == 4)
137         return max(min(1.f - (fshade * shadescale / frealmaxshade), 1.f), 0.f);
138 
139     float const shadebound = (float)((shadescale_unbounded || shade>=numshades) ? numshades : numshades-1);
140     float const scaled_shade = fshade*shadescale;
141     float const clamped_shade = min(max(scaled_shade, 0.f), shadebound);
142 
143     return ((float)(numshades-clamped_shade))/(float)numshades;
144 }
145 
146 #define POLYMOST_CHOOSE_FOG_PAL(fogpal, pal) \
147     ((fogpal) ? (fogpal) : (pal))
get_floor_fogpal(usectorptr_t const sec)148 static FORCE_INLINE int32_t get_floor_fogpal(usectorptr_t const sec)
149 {
150     return POLYMOST_CHOOSE_FOG_PAL(sec->fogpal, sec->floorpal);
151 }
get_ceiling_fogpal(usectorptr_t const sec)152 static FORCE_INLINE int32_t get_ceiling_fogpal(usectorptr_t const sec)
153 {
154     return POLYMOST_CHOOSE_FOG_PAL(sec->fogpal, sec->ceilingpal);
155 }
fogshade(int32_t const shade,int32_t const pal)156 static FORCE_INLINE int32_t fogshade(int32_t const shade, int32_t const pal)
157 {
158     polytintflags_t const tintflags = hictinting[pal].f;
159     return (globalflags & GLOBAL_NO_GL_FOGSHADE || tintflags & HICTINT_NOFOGSHADE) ? 0 : shade;
160 }
161 
check_nonpow2(int32_t const x)162 static FORCE_INLINE int check_nonpow2(int32_t const x)
163 {
164     return (x > 1 && (x&(x-1)));
165 }
166 
167 // Are we using the mode that uploads non-power-of-two wall textures like they
168 // render in classic?
polymost_is_npotmode(void)169 static FORCE_INLINE int polymost_is_npotmode(void)
170 {
171     // The glinfo.texnpot check is so we don't have to deal with that case in
172     // gloadtile_art().
173     return glinfo.texnpot &&
174         // r_npotwallmode is NYI for hightiles. We require r_hightile off
175         // because in calc_ypanning(), the repeat would be multiplied by a
176         // factor even if no modified texture were loaded.
177         !usehightile &&
178 #ifdef NEW_MAP_FORMAT
179         g_loadedMapVersion < 10 &&
180 #endif
181         r_npotwallmode == 1;
182 }
183 
polymost_invsqrt_approximation(float x)184 static inline float polymost_invsqrt_approximation(float x)
185 {
186 #ifdef B_LITTLE_ENDIAN
187     float const haf = x * .5f;
188     union { float f; uint32_t i; } n = { x };
189     n.i = 0x5f375a86 - (n.i >> 1);
190     return n.f * (1.5f - haf * (n.f * n.f));
191 #else
192     // this is the comment
193     return 1.f / Bsqrtf(x);
194 #endif
195 }
196 
197 // Flags of the <dameth> argument of various functions
198 enum {
199     DAMETH_NOMASK = 0,
200     DAMETH_MASK = 1,
201     DAMETH_TRANS1 = 2,
202     DAMETH_TRANS2 = 3,
203 
204     DAMETH_MASKPROPS = 3,
205 
206     DAMETH_CLAMPED = 4,
207 
208     DAMETH_WALL = 32,  // signals a texture for a wall (for r_npotwallmode)
209 
210     DAMETH_INDEXED = 512,
211 
212     DAMETH_N64 = 1024,
213     DAMETH_N64_INTENSIVITY = 2048,
214     DAMETH_N64_SCALED = 2097152,
215 
216     // used internally by polymost_domost
217     DAMETH_BACKFACECULL = -1,
218 
219     // used internally by uploadtexture
220     DAMETH_NODOWNSIZE = 4096,
221     DAMETH_HI = 8192,
222     DAMETH_NOFIX = 16384,
223     DAMETH_NOTEXCOMPRESS = 32768,
224     DAMETH_HASALPHA = 65536,
225     DAMETH_ONEBITALPHA = 131072,
226     DAMETH_ARTIMMUNITY = 262144,
227 
228     DAMETH_HASFULLBRIGHT = 524288,
229     DAMETH_NPOTWALL = 1048576,
230 
231     DAMETH_UPLOADTEXTURE_MASK =
232         DAMETH_HI |
233         DAMETH_NODOWNSIZE |
234         DAMETH_NOFIX |
235         DAMETH_NOTEXCOMPRESS |
236         DAMETH_HASALPHA |
237         DAMETH_ONEBITALPHA |
238         DAMETH_ARTIMMUNITY |
239         DAMETH_HASFULLBRIGHT |
240         DAMETH_NPOTWALL,
241 };
242 
243 #define DAMETH_NARROW_MASKPROPS(dameth) (((dameth)&(~DAMETH_TRANS1))|(((dameth)&DAMETH_TRANS1)>>1))
244 EDUKE32_STATIC_ASSERT(DAMETH_NARROW_MASKPROPS(DAMETH_MASKPROPS) == DAMETH_MASK);
245 EDUKE32_STATIC_ASSERT(DAMETH_NARROW_MASKPROPS(DAMETH_CLAMPED) == DAMETH_CLAMPED);
246 
247 #define TO_DAMETH_NODOWNSIZE(hicr_flags) (((hicr_flags)&HICR_NODOWNSIZE)<<8)
248 EDUKE32_STATIC_ASSERT(TO_DAMETH_NODOWNSIZE(HICR_NODOWNSIZE) == DAMETH_NODOWNSIZE);
249 #define TO_DAMETH_NOTEXCOMPRESS(hicr_flags) (((hicr_flags)&HICR_NOTEXCOMPRESS)<<15)
250 EDUKE32_STATIC_ASSERT(TO_DAMETH_NOTEXCOMPRESS(HICR_NOTEXCOMPRESS) == DAMETH_NOTEXCOMPRESS);
251 #define TO_DAMETH_ARTIMMUNITY(hicr_flags) (((hicr_flags)&HICR_ARTIMMUNITY)<<13)
252 EDUKE32_STATIC_ASSERT(TO_DAMETH_ARTIMMUNITY(HICR_ARTIMMUNITY) == DAMETH_ARTIMMUNITY);
253 
254 // Do we want a NPOT-y-as-classic texture for this <dameth> and <ysiz>?
polymost_want_npotytex(int32_t dameth,int32_t ysiz)255 static FORCE_INLINE int polymost_want_npotytex(int32_t dameth, int32_t ysiz)
256 {
257     return videoGetRenderMode() != REND_POLYMER &&  // r_npotwallmode NYI in Polymer
258         polymost_is_npotmode() && (dameth&DAMETH_WALL) && check_nonpow2(ysiz);
259 }
260 
261 // pthtyp pth->flags bits
262 enum pthtyp_flags {
263     PTH_CLAMPED = 1,
264     PTH_HIGHTILE = 2,
265     PTH_SKYBOX = 4,
266     PTH_HASALPHA = 8,
267     PTH_HASFULLBRIGHT = 16,
268     PTH_NPOTWALL = DAMETH_WALL,  // r_npotwallmode=1 generated texture
269     PTH_FORCEFILTER = 64,
270 
271     PTH_INVALIDATED = 128,
272 
273     PTH_NOTRANSFIX = 256, // fixtransparency() bypassed
274 
275     PTH_INDEXED = 512,
276     PTH_ONEBITALPHA = 1024,
277 
278     PTH_N64 = 2048,
279     PTH_N64_INTENSIVITY = 4096,
280     PTH_N64_SCALED = 8192,
281 };
282 
283 typedef struct pthtyp_t
284 {
285     struct pthtyp_t *next;
286     struct pthtyp_t *ofb; // fullbright pixels
287     hicreplctyp     *hicr;
288 
289     uint32_t        glpic;
290     vec2f_t         scale;
291     vec2_t          siz;
292     int16_t         picnum;
293 
294     uint16_t        flags; // see pthtyp_flags
295     polytintflags_t effects;
296     char            palnum;
297     char            shade;
298     char            skyface;
299 } pthtyp;
300 
301 // DAMETH -> PTH conversions
302 #define TO_PTH_CLAMPED(dameth) (((dameth)&DAMETH_CLAMPED)>>2)
303 EDUKE32_STATIC_ASSERT(TO_PTH_CLAMPED(DAMETH_CLAMPED) == PTH_CLAMPED);
304 #define TO_PTH_NOTRANSFIX(dameth) ((((~(dameth))&DAMETH_MASK)<<8)&(((~(dameth))&DAMETH_TRANS1)<<7))
305 EDUKE32_STATIC_ASSERT(TO_PTH_NOTRANSFIX(DAMETH_NOMASK) == PTH_NOTRANSFIX);
306 EDUKE32_STATIC_ASSERT(TO_PTH_NOTRANSFIX(DAMETH_MASK) == 0);
307 EDUKE32_STATIC_ASSERT(TO_PTH_NOTRANSFIX(DAMETH_TRANS1) == 0);
308 EDUKE32_STATIC_ASSERT(TO_PTH_NOTRANSFIX(DAMETH_MASKPROPS) == 0);
309 #define TO_PTH_INDEXED(dameth) ((dameth)&DAMETH_INDEXED)
310 EDUKE32_STATIC_ASSERT(TO_PTH_INDEXED(DAMETH_INDEXED) == PTH_INDEXED);
311 #define TO_PTH_N64(dameth) (((dameth)&DAMETH_N64)<<1)
312 EDUKE32_STATIC_ASSERT(TO_PTH_N64(DAMETH_N64) == PTH_N64);
313 #define TO_PTH_N64_INTENSIVITY(dameth) (((dameth)&DAMETH_N64_INTENSIVITY)<<1)
314 EDUKE32_STATIC_ASSERT(TO_PTH_N64_INTENSIVITY(DAMETH_N64_INTENSIVITY) == PTH_N64_INTENSIVITY);
315 #define TO_PTH_N64_SCALED(dameth) (((dameth)&DAMETH_N64_SCALED)>>8)
316 EDUKE32_STATIC_ASSERT(TO_PTH_N64_SCALED(DAMETH_N64_SCALED) == PTH_N64_SCALED);
317 
318 extern void gloadtile_art(int32_t,int32_t,int32_t,int32_t,int32_t,pthtyp *,int32_t);
319 extern int32_t gloadtile_hi(int32_t,int32_t,int32_t,hicreplctyp *,int32_t,pthtyp *,int32_t,polytintflags_t);
320 
321 extern int32_t globalnoeffect;
322 extern int32_t drawingskybox;
323 extern int32_t hicprecaching;
324 extern float fcosglobalang, fsinglobalang;
325 extern float fxdim, fydim, fydimen, fviewingrange;
326 
327 extern char ptempbuf[MAXWALLSB<<1];
328 
329 extern hitdata_t polymost_hitdata;
330 
331 #include "texcache.h"
332 
333 extern void polymost_setupglowtexture(int32_t texunits, int32_t tex);
334 extern void polymost_setupdetailtexture(int32_t texunits, int32_t tex);
335 
336 #ifdef __cplusplus
337 }
338 #endif
339 
340 #endif
341 
342 #endif
343