Subversion Repositories eduke32

Rev

Rev 7787 | Rev 7843 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
5 Plagman 1
/**************************************************************************************************
5001 terminx 2
"POLYMOST" code originally written by Ken Silverman
5 Plagman 3
Ken Silverman's official web site: http://www.advsys.net/ken
6658 pogokeen 4
 
5
"POLYMOST2" changes Copyright (c) 2018, Alex Dawson
5 Plagman 6
**************************************************************************************************/
7
 
1173 terminx 8
 
1820 terminx 9
#ifdef USE_OPENGL
1173 terminx 10
 
11
#include "build.h"
7421 terminx 12
#include "common.h"
13
#include "engine_priv.h"
14
#include "kplib.h"
3758 terminx 15
#include "mdsprite.h"
1173 terminx 16
#include "polymost.h"
6883 pogokeen 17
#include "tilepacker.h"
1173 terminx 18
 
19
extern char textfont[2048], smalltextfont[2048];
20
 
1205 terminx 21
int32_t rendmode=0;
4439 terminx 22
int32_t usemodels=1;
23
int32_t usehightile=1;
5 Plagman 24
 
2002 helixhorne 25
typedef struct { float x, cy[2], fy[2]; int32_t tag; int16_t n, p, ctag, ftag; } vsptyp;
6524 terminx 26
#define VSPMAX 2048 //<- careful!
5 Plagman 27
static vsptyp vsp[VSPMAX];
7737 pogokeen 28
static int32_t gtag, viewportNodeCount;
7400 terminx 29
static float xbl, xbr, xbt, xbb;
7379 terminx 30
int32_t domost_rejectcount;
7400 terminx 31
#ifdef YAX_ENABLE
32
typedef struct { float x, cy[2]; int32_t tag; int16_t n, p, ctag; } yax_vsptyp;
33
static yax_vsptyp yax_vsp[YAX_MAXBUNCHES*2][VSPMAX];
34
typedef struct { float x0, x1, cy[2], fy[2]; } yax_hole_t;
35
static yax_hole_t yax_holecf[2][VSPMAX];
36
static int32_t yax_holencf[2];
37
static int32_t yax_drawcf = -1;
38
#endif
5 Plagman 39
 
4605 terminx 40
static float dxb1[MAXWALLSB], dxb2[MAXWALLSB];
5 Plagman 41
 
7754 pogokeen 42
//POGOTODO: the SCISDIST could be set to 0 now to allow close objects to render properly,
43
//          but there's a nasty rendering bug that needs to be dug into when setting SCISDIST lower than 1
44
#define SCISDIST 1.f  //close plane clipping distance
5 Plagman 45
 
7412 terminx 46
#define SOFTROTMAT 0
47
 
3403 helixhorne 48
float shadescale = 1.0f;
1848 helixhorne 49
int32_t shadescale_unbounded = 0;
379 terminx 50
 
7681 pogokeen 51
int32_t r_polymostDebug = 0;
6658 pogokeen 52
int32_t r_enablepolymost2 = 0;
6515 hendricks2 53
int32_t r_usenewshading = 4;
7413 terminx 54
int32_t r_npotwallmode = 2;
1943 helixhorne 55
 
4605 terminx 56
static float gviewxrange;
7656 terminx 57
static float ghoriz, ghoriz2;
7403 terminx 58
double gxyaspect;
7656 terminx 59
float gyxscale, ghalfx, grhalfxdown10, grhalfxdown10x, ghalfy;
4605 terminx 60
float gcosang, gsinang, gcosang2, gsinang2;
61
float gchang, gshang, gctang, gstang, gvisibility;
62
float gtang = 0.f;
5075 terminx 63
 
7413 terminx 64
static vec3d_t xtex, ytex, otex, xtex2, ytex2, otex2;
5075 terminx 65
 
4667 terminx 66
float fcosglobalang, fsinglobalang;
4768 hendricks2 67
float fxdim, fydim, fydimen, fviewingrange;
1706 helixhorne 68
 
7742 terminx 69
float fsearchx, fsearchy, fsearchz;
70
int psectnum, pwallnum, pbottomwall, pisbottomwall, psearchstat, doeditorcheck = 0;
71
 
5075 terminx 72
static int32_t drawpoly_srepeat = 0, drawpoly_trepeat = 0;
6652 pogokeen 73
#define MAX_DRAWPOLY_VERTS 8
6662 pogokeen 74
#define BUFFER_OFFSET(bytes) (GLintptr) ((GLubyte*) NULL + (bytes))
75
// these cvars are never used directly in rendering -- only when glinit() is called/renderer reset
76
// We do this because we don't want to accidentally overshoot our existing buffer's bounds
77
uint32_t r_persistentStreamBuffer = 1;
78
uint32_t persistentStreamBuffer = r_persistentStreamBuffer;
79
int32_t r_drawpolyVertsBufferLength = 30000;
80
int32_t drawpolyVertsBufferLength = r_drawpolyVertsBufferLength;
81
static GLuint drawpolyVertsID = 0;
82
static GLint drawpolyVertsOffset = 0;
83
static int32_t drawpolyVertsSubBufferIndex = 0;
6883 pogokeen 84
static GLsync drawpolyVertsSync[3] = { 0 };
6662 pogokeen 85
static float defaultDrawpolyVertsArray[MAX_DRAWPOLY_VERTS*5];
86
static float* drawpolyVerts = defaultDrawpolyVertsArray;
590 plagman 87
 
3041 helixhorne 88
struct glfiltermodes glfiltermodes[NUMGLFILTERMODES] =
584 terminx 89
{
90
    {"GL_NEAREST",GL_NEAREST,GL_NEAREST},
91
    {"GL_LINEAR",GL_LINEAR,GL_LINEAR},
92
    {"GL_NEAREST_MIPMAP_NEAREST",GL_NEAREST_MIPMAP_NEAREST,GL_NEAREST},
93
    {"GL_LINEAR_MIPMAP_NEAREST",GL_LINEAR_MIPMAP_NEAREST,GL_LINEAR},
94
    {"GL_NEAREST_MIPMAP_LINEAR",GL_NEAREST_MIPMAP_LINEAR,GL_NEAREST},
95
    {"GL_LINEAR_MIPMAP_LINEAR",GL_LINEAR_MIPMAP_LINEAR,GL_LINEAR}
96
};
5 Plagman 97
 
5929 terminx 98
int32_t glanisotropy = 0;            // 0 = maximum supported by card
5108 hendricks2 99
int32_t gltexfiltermode = TEXFILTER_OFF;
5001 terminx 100
 
101
#ifdef EDUKE32_GLES
5690 hendricks2 102
int32_t glusetexcompr = 2;
5001 terminx 103
int32_t glusetexcache = 0, glusememcache = 0;
104
#else
1205 terminx 105
int32_t glusetexcompr = 1;
2145 helixhorne 106
int32_t glusetexcache = 2, glusememcache = 1;
5075 terminx 107
int32_t r_polygonmode = 0;     // 0:GL_FILL,1:GL_LINE,2:GL_POINT //FUK
5526 hendricks2 108
static int32_t lastglpolygonmode = 0; //FUK
109
#endif
110
#ifdef USE_GLEXT
1205 terminx 111
int32_t glmultisample = 0, glnvmultisamplehint = 0;
5001 terminx 112
int32_t r_detailmapping = 1;
113
int32_t r_glowmapping = 1;
114
#endif
115
 
1205 terminx 116
int32_t gltexmaxsize = 0;      // 0 means autodetection on first run
117
int32_t gltexmiplevel = 0;              // discards this many mipmap levels
118
int32_t glprojectionhacks = 1;
5 Plagman 119
static GLuint polymosttext = 0;
3784 terminx 120
int32_t glrendmode = REND_POLYMOST;
7650 terminx 121
int32_t r_shadeinterpolate = 1;
228 Plagman 122
 
3146 helixhorne 123
// This variable, and 'shadeforfullbrightpass' control the drawing of
124
// fullbright tiles.  Also see 'fullbrightloadingpass'.
228 Plagman 125
 
5275 terminx 126
int32_t r_fullbrights = 1;
1205 terminx 127
int32_t r_vertexarrays = 1;
5526 hendricks2 128
#ifdef USE_GLEXT
6662 pogokeen 129
//POGOTODO: we no longer support rendering without VBOs -- update any outdated pre-GL2 code that renders without VBOs
1205 terminx 130
int32_t r_vbos = 1;
131
int32_t r_vbocount = 64;
5526 hendricks2 132
#endif
1205 terminx 133
int32_t r_animsmoothing = 1;
3387 helixhorne 134
int32_t r_downsize = 0;
1634 terminx 135
int32_t r_downsizevar = -1;
916 terminx 136
 
7656 terminx 137
int32_t r_yshearing = 0;
138
 
1329 terminx 139
// used for fogcalc
5079 terminx 140
static float fogresult, fogresult2;
141
coltypef fogcol, fogtable[MAXPALOOKUPS];
5 Plagman 142
 
6776 pogokeen 143
static uint32_t currentShaderProgramID = 0;
6883 pogokeen 144
static GLenum currentActiveTexture = 0;
145
static uint32_t currentTextureID = 0;
6776 pogokeen 146
 
6658 pogokeen 147
static GLuint quadVertsID = 0;
6776 pogokeen 148
static GLuint polymost2BasicShaderProgramID = 0;
6658 pogokeen 149
static GLint texSamplerLoc = -1;
150
static GLint fullBrightSamplerLoc = -1;
151
static GLint projMatrixLoc = -1;
152
static GLint mvMatrixLoc = -1;
153
static GLint texOffsetLoc = -1;
154
static GLint texScaleLoc = -1;
155
static GLint tintLoc = -1;
156
static GLint alphaLoc = -1;
157
static GLint fogRangeLoc = -1;
158
static GLint fogColorLoc = -1;
159
 
6777 pogokeen 160
#define PALSWAP_TEXTURE_SIZE 2048
6776 pogokeen 161
int32_t r_useindexedcolortextures = -1;
6883 pogokeen 162
static GLuint tilesheetTexIDs[MAXTILESHEETS];
163
static GLint tilesheetSize = 0;
164
static vec2f_t tilesheetHalfTexelSize = { 0.f, 0.f };
6776 pogokeen 165
static int32_t lastbasepal = -1;
166
static GLuint paletteTextureIDs[MAXBASEPALS];
6777 pogokeen 167
static GLuint palswapTextureID = 0;
7793 pogokeen 168
extern char const *polymost1Frag;
169
extern char const *polymost1Vert;
6776 pogokeen 170
static GLuint polymost1CurrentShaderProgramID = 0;
171
static GLuint polymost1BasicShaderProgramID = 0;
172
static GLuint polymost1ExtendedShaderProgramID = 0;
173
static GLint polymost1TexSamplerLoc = -1;
174
static GLint polymost1PalSwapSamplerLoc = -1;
175
static GLint polymost1PaletteSamplerLoc = -1;
176
static GLint polymost1DetailSamplerLoc = -1;
177
static GLint polymost1GlowSamplerLoc = -1;
6883 pogokeen 178
static GLint polymost1TexturePosSizeLoc = -1;
179
static vec4f_t polymost1TexturePosSize = { 0.f, 0.f, 1.f, 1.f };
180
static GLint polymost1HalfTexelSizeLoc = -1;
181
static vec2f_t polymost1HalfTexelSize = { 0.f, 0.f };
6777 pogokeen 182
static GLint polymost1PalswapPosLoc = -1;
6883 pogokeen 183
static vec2f_t polymost1PalswapPos = { 0.f, 0.f };
6777 pogokeen 184
static GLint polymost1PalswapSizeLoc = -1;
6883 pogokeen 185
static vec2f_t polymost1PalswapSize = { 0.f, 0.f };
186
static vec2f_t polymost1PalswapInnerSize = { 0.f, 0.f };
7783 pogokeen 187
static GLint polymost1ClampLoc = -1;
188
static float polymost1Clamp = 0.f;
6776 pogokeen 189
static GLint polymost1ShadeLoc = -1;
190
static float polymost1Shade = 0.f;
7412 terminx 191
static GLint polymost1NumShadesLoc = -1;
192
static float polymost1NumShades = 64.f;
193
static GLint polymost1VisFactorLoc = -1;
194
static float polymost1VisFactor = 128.f;
6776 pogokeen 195
static GLint polymost1FogEnabledLoc = -1;
196
static float polymost1FogEnabled = 1.f;
197
static GLint polymost1UseColorOnlyLoc = -1;
198
static float polymost1UseColorOnly = 0.f;
199
static GLint polymost1UsePaletteLoc = -1;
200
static float polymost1UsePalette = 1.f;
201
static GLint polymost1UseDetailMappingLoc = -1;
202
static float polymost1UseDetailMapping = 0.f;
203
static GLint polymost1UseGlowMappingLoc = -1;
204
static float polymost1UseGlowMapping = 0.f;
7413 terminx 205
static GLint polymost1NPOTEmulationLoc = -1;
206
static float polymost1NPOTEmulation = 0.f;
207
static GLint polymost1NPOTEmulationFactorLoc = -1;
208
static float polymost1NPOTEmulationFactor = 1.f;
209
static GLint polymost1NPOTEmulationXOffsetLoc = -1;
210
static float polymost1NPOTEmulationXOffset = 0.f;
7412 terminx 211
static GLint polymost1RotMatrixLoc = -1;
212
static float polymost1RotMatrix[16] = { 1.f, 0.f, 0.f, 0.f,
213
                                        0.f, 1.f, 0.f, 0.f,
214
                                        0.f, 0.f, 1.f, 0.f,
215
                                        0.f, 0.f, 0.f, 1.f };
7650 terminx 216
static GLint polymost1ShadeInterpolateLoc = -1;
217
static float polymost1ShadeInterpolate = 1.f;
6776 pogokeen 218
 
6175 terminx 219
static inline float float_trans(uint32_t maskprops, uint8_t blend)
5888 hendricks2 220
{
221
    switch (maskprops)
222
    {
223
    case DAMETH_TRANS1:
224
    case DAMETH_TRANS2:
225
        return glblend[blend].def[maskprops-2].alpha;
226
    default:
227
        return 1.0f;
228
    }
229
}
4623 terminx 230
 
3758 terminx 231
char ptempbuf[MAXWALLSB<<1];
1173 terminx 232
 
1064 terminx 233
// polymost ART sky control
1205 terminx 234
int32_t r_parallaxskyclamping = 1;
6521 hendricks2 235
int32_t r_parallaxskypanning = 1;
1064 terminx 236
 
2045 helixhorne 237
#define MIN_CACHETIME_PRINT 10
1784 helixhorne 238
 
4675 terminx 239
// this was faster in MSVC but slower with GCC... currently unknown on ARM where both
240
// the FPU and possibly the optimization path in the compiler need improvement
241
#if 0
5158 helixhorne 242
static inline int32_t __float_as_int(float f) { return *(int32_t *) &f; }
4675 terminx 243
static inline float __int_as_float(int32_t d) { return *(float *) &d; }
244
static inline float Bfabsf(float f) { return __int_as_float(__float_as_int(f)&0x7fffffff); }
245
#else
246
#define Bfabsf fabsf
247
#endif
248
 
1652 terminx 249
int32_t mdtims, omdtims;
5075 terminx 250
uint8_t alphahackarray[MAXTILES];
1205 terminx 251
int32_t drawingskybox = 0;
3758 terminx 252
int32_t hicprecaching = 0;
5 Plagman 253
 
5277 terminx 254
hitdata_t polymost_hitdata;
255
 
7681 pogokeen 256
void polymost_outputGLDebugMessage(uint8_t severity, const char* format, ...)
257
{
258
    static char msg[8192];
259
    va_list vArgs;
260
 
261
    if (!glinfo.debugoutput ||
262
        r_polymostDebug < severity)
263
    {
264
        return;
265
    }
266
 
267
    va_start(vArgs, format);
268
    Bvsnprintf(msg, sizeof(msg), format, vArgs);
269
    va_end(vArgs);
270
 
271
    glDebugMessageInsertARB(GL_DEBUG_SOURCE_APPLICATION_ARB,
272
                            GL_DEBUG_TYPE_OTHER_ARB,
273
                            0,
274
                            GL_DEBUG_SEVERITY_HIGH_ARB+severity-1,
275
                            -1,
276
                            msg);
277
}
278
 
4690 terminx 279
#if 0
1221 terminx 280
static inline int32_t gltexmayhavealpha(int32_t dapicnum, int32_t dapalnum)
5 Plagman 281
{
3146 helixhorne 282
    const int32_t j = (dapicnum&(GLTEXCACHEADSIZ-1));
109 terminx 283
    pthtyp *pth;
5 Plagman 284
 
3781 terminx 285
    for (pth=texcache.list[j]; pth; pth=pth->next)
3146 helixhorne 286
        if (pth->picnum == dapicnum && pth->palnum == dapalnum)
4486 helixhorne 287
            return ((pth->flags&PTH_HASALPHA) != 0);
3146 helixhorne 288
 
289
    return 1;
5 Plagman 290
}
4690 terminx 291
#endif
5 Plagman 292
 
1205 terminx 293
void gltexinvalidate(int32_t dapicnum, int32_t dapalnum, int32_t dameth)
5 Plagman 294
{
5075 terminx 295
    const int32_t pic = (dapicnum&(GLTEXCACHEADSIZ-1));
5 Plagman 296
 
5075 terminx 297
    for (pthtyp *pth=texcache.list[pic]; pth; pth=pth->next)
4486 helixhorne 298
        if (pth->picnum == dapicnum && pth->palnum == dapalnum &&
299
            (pth->flags & PTH_CLAMPED) == TO_PTH_CLAMPED(dameth))
248 terminx 300
        {
4486 helixhorne 301
            pth->flags |= PTH_INVALIDATED;
302
            if (pth->flags & PTH_HASFULLBRIGHT)
303
                pth->ofb->flags |= PTH_INVALIDATED;
248 terminx 304
        }
5 Plagman 305
}
306
 
109 terminx 307
//Make all textures "dirty" so they reload, but not re-allocate
308
//This should be much faster than polymost_glreset()
309
//Use this for palette effects ... but not ones that change every frame!
3765 terminx 310
void gltexinvalidatetype(int32_t type)
5 Plagman 311
{
5829 terminx 312
    for (bssize_t j=0; j<=GLTEXCACHEADSIZ-1; j++)
3758 terminx 313
    {
5075 terminx 314
        for (pthtyp *pth=texcache.list[j]; pth; pth=pth->next)
248 terminx 315
        {
6776 pogokeen 316
            if (type == INVALIDATE_ALL ||
317
                (type == INVALIDATE_ALL_NON_INDEXED && !(pth->flags & PTH_INDEXED)) ||
318
                (type == INVALIDATE_ART && pth->hicr == NULL) ||
319
                (type == INVALIDATE_ART_NON_INDEXED && pth->hicr == NULL && !(pth->flags & PTH_INDEXED)))
415 terminx 320
            {
4486 helixhorne 321
                pth->flags |= PTH_INVALIDATED;
322
                if (pth->flags & PTH_HASFULLBRIGHT)
323
                    pth->ofb->flags |= PTH_INVALIDATED;
415 terminx 324
            }
325
        }
3758 terminx 326
    }
327
 
5494 hendricks2 328
    clearskins(type);
329
 
415 terminx 330
#ifdef DEBUGGINGAIDS
3758 terminx 331
    OSD_Printf("gltexinvalidateall()\n");
415 terminx 332
#endif
333
}
334
 
5001 terminx 335
static void bind_2d_texture(GLuint texture, int filter)
3041 helixhorne 336
{
5001 terminx 337
    if (filter == -1)
338
        filter = gltexfiltermode;
339
 
6656 pogokeen 340
    glBindTexture(GL_TEXTURE_2D, texture);
341
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, glfiltermodes[filter].mag);
342
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, glfiltermodes[filter].min);
5526 hendricks2 343
#ifdef USE_GLEXT
4605 terminx 344
    if (glinfo.maxanisotropy > 1.f)
6656 pogokeen 345
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, glanisotropy);
5001 terminx 346
#endif
3041 helixhorne 347
}
348
 
584 terminx 349
void gltexapplyprops(void)
5 Plagman 350
{
6829 terminx 351
    if (videoGetRenderMode() == REND_CLASSIC)
3628 helixhorne 352
        return;
353
 
4605 terminx 354
    if (glinfo.maxanisotropy > 1.f)
109 terminx 355
    {
3041 helixhorne 356
        if (glanisotropy <= 0 || glanisotropy > glinfo.maxanisotropy)
357
            glanisotropy = (int32_t)glinfo.maxanisotropy;
109 terminx 358
    }
5 Plagman 359
 
3041 helixhorne 360
    gltexfiltermode = clamp(gltexfiltermode, 0, NUMGLFILTERMODES-1);
6776 pogokeen 361
    r_useindexedcolortextures = !gltexfiltermode;
3041 helixhorne 362
 
5829 terminx 363
    for (bssize_t i=0; i<=GLTEXCACHEADSIZ-1; i++)
584 terminx 364
    {
5075 terminx 365
        for (pthtyp *pth=texcache.list[i]; pth; pth=pth->next)
584 terminx 366
        {
6776 pogokeen 367
            if (pth->flags & PTH_INDEXED)
368
            {
369
                //POGO: indexed textures should not be filtered
370
                continue;
371
            }
372
 
7109 terminx 373
            int32_t const filter = (pth->flags & PTH_FORCEFILTER) ? TEXFILTER_ON : -1;
3041 helixhorne 374
 
5108 hendricks2 375
            bind_2d_texture(pth->glpic, filter);
5001 terminx 376
 
377
            if (r_fullbrights && pth->flags & PTH_HASFULLBRIGHT)
5108 hendricks2 378
                bind_2d_texture(pth->ofb->glpic, filter);
109 terminx 379
        }
380
    }
5 Plagman 381
 
5829 terminx 382
    for (bssize_t i=0; i<nextmodelid; i++)
5075 terminx 383
    {
384
        md2model_t *m = (md2model_t *)models[i];
5001 terminx 385
 
5075 terminx 386
        if (m->mdnum < 2)
387
            continue;
388
 
6214 hendricks2 389
        for (bssize_t j = 0; j < m->numskins * HICTINT_MEMORY_COMBINATIONS; j++)
5001 terminx 390
        {
5075 terminx 391
            if (!m->texid[j])
392
                continue;
5001 terminx 393
            bind_2d_texture(m->texid[j], -1);
394
        }
109 terminx 395
 
5075 terminx 396
        for (mdskinmap_t *sk = m->skinmap; sk; sk = sk->next)
6214 hendricks2 397
            for (bssize_t j = 0; j < HICTINT_MEMORY_COMBINATIONS; j++)
109 terminx 398
            {
5075 terminx 399
                if (!sk->texid[j])
400
                    continue;
7109 terminx 401
                bind_2d_texture(sk->texid[j], (sk->flags & HICR_FORCEFILTER) ? TEXFILTER_ON : -1);
109 terminx 402
            }
403
    }
5 Plagman 404
}
405
 
406
//--------------------------------------------------------------------------------------------------
3758 terminx 407
 
7656 terminx 408
float glox1, gloy1, glox2, gloy2, gloyxscale, gloxyaspect, glohoriz2, glotang;
5 Plagman 409
 
109 terminx 410
//Use this for both initialization and uninitialization of OpenGL.
1205 terminx 411
static int32_t gltexcacnum = -1;
1652 terminx 412
 
6658 pogokeen 413
//in-place multiply m0=m0*m1
7072 terminx 414
static float* multiplyMatrix4f(float m0[4*4], const float m1[4*4])
6658 pogokeen 415
{
416
    float mR[4*4];
6700 hendricks2 417
 
6658 pogokeen 418
#define multMatrix4RowCol(r, c) mR[r*4+c] = m0[r*4]*m1[c] + m0[r*4+1]*m1[c+4] + m0[r*4+2]*m1[c+8] + m0[r*4+3]*m1[c+12]
6700 hendricks2 419
 
6658 pogokeen 420
    multMatrix4RowCol(0, 0);
421
    multMatrix4RowCol(0, 1);
422
    multMatrix4RowCol(0, 2);
423
    multMatrix4RowCol(0, 3);
6700 hendricks2 424
 
6658 pogokeen 425
    multMatrix4RowCol(1, 0);
426
    multMatrix4RowCol(1, 1);
427
    multMatrix4RowCol(1, 2);
428
    multMatrix4RowCol(1, 3);
6700 hendricks2 429
 
6658 pogokeen 430
    multMatrix4RowCol(2, 0);
431
    multMatrix4RowCol(2, 1);
432
    multMatrix4RowCol(2, 2);
433
    multMatrix4RowCol(2, 3);
6700 hendricks2 434
 
6658 pogokeen 435
    multMatrix4RowCol(3, 0);
436
    multMatrix4RowCol(3, 1);
437
    multMatrix4RowCol(3, 2);
438
    multMatrix4RowCol(3, 3);
6700 hendricks2 439
 
6658 pogokeen 440
    Bmemcpy(m0, mR, sizeof(float)*4*4);
6700 hendricks2 441
 
6658 pogokeen 442
    return m0;
6700 hendricks2 443
 
6658 pogokeen 444
#undef multMatrix4RowCol
445
}
446
 
447
static void calcmat(vec3f_t a0, const vec2f_t *offset, float f, float mat[16], int16_t angle)
448
{
449
    float g;
450
    float k0, k1, k2, k3, k4, k5, k6, k7;
451
 
452
    k0 = a0.y;
453
    k1 = a0.x;
454
    a0.x += offset->x;
455
    a0.z += offset->y;
456
    f = gcosang2*gshang;
457
    g = gsinang2*gshang;
458
    k4 = (float)sintable[(angle+1024)&2047] * (1.f/16384.f);
459
    k5 = (float)sintable[(angle+512)&2047] * (1.f/16384.f);
460
    k2 = k0*(1-k4)+k1*k5;
461
    k3 = k1*(1-k4)-k0*k5;
462
    k6 = f*gstang - gsinang*gctang; k7 = g*gstang + gcosang*gctang;
463
    mat[0] = k4*k6 + k5*k7; mat[4] = gchang*gstang; mat[ 8] = k4*k7 - k5*k6; mat[12] = k2*k6 + k3*k7;
464
    k6 = f*gctang + gsinang*gstang; k7 = g*gctang - gcosang*gstang;
465
    mat[1] = k4*k6 + k5*k7; mat[5] = gchang*gctang; mat[ 9] = k4*k7 - k5*k6; mat[13] = k2*k6 + k3*k7;
466
    k6 =           gcosang2*gchang; k7 =           gsinang2*gchang;
467
    mat[2] = k4*k6 + k5*k7; mat[6] =-gshang;        mat[10] = k4*k7 - k5*k6; mat[14] = k2*k6 + k3*k7;
468
 
469
    mat[12] = (mat[12] + a0.y*mat[0]) + (a0.z*mat[4] + a0.x*mat[ 8]);
470
    mat[13] = (mat[13] + a0.y*mat[1]) + (a0.z*mat[5] + a0.x*mat[ 9]);
471
    mat[14] = (mat[14] + a0.y*mat[2]) + (a0.z*mat[6] + a0.x*mat[10]);
472
}
473
 
7787 hendricks2 474
static GLuint polymost2_compileShader(GLenum shaderType, const char* const source, int * pLength = nullptr)
6658 pogokeen 475
{
476
    GLuint shaderID = glCreateShader(shaderType);
477
    if (shaderID == 0)
478
    {
479
        return 0;
480
    }
6700 hendricks2 481
 
6658 pogokeen 482
    glShaderSource(shaderID,
483
                   1,
7782 pogokeen 484
                   &source,
7787 hendricks2 485
                   pLength);
6658 pogokeen 486
    glCompileShader(shaderID);
6700 hendricks2 487
 
6671 pogokeen 488
    GLint compileStatus;
489
    glGetShaderiv(shaderID, GL_COMPILE_STATUS, &compileStatus);
490
    if (!compileStatus)
6658 pogokeen 491
    {
6671 pogokeen 492
        GLint logLength;
493
        glGetShaderiv(shaderID, GL_INFO_LOG_LENGTH, &logLength);
6960 pogokeen 494
        OSD_Printf("Compile Status: %u\n", compileStatus);
6671 pogokeen 495
        if (logLength > 0)
496
        {
7079 terminx 497
            char *infoLog = (char*)Xmalloc(logLength);
6671 pogokeen 498
            glGetShaderInfoLog(shaderID, logLength, &logLength, infoLog);
499
            OSD_Printf("Log:\n%s\n", infoLog);
500
            free(infoLog);
501
        }
6658 pogokeen 502
    }
6700 hendricks2 503
 
6658 pogokeen 504
    return shaderID;
505
}
506
 
7787 hendricks2 507
static GLuint polymost2_compileShader(GLenum shaderType, const char* const source, int length)
508
{
509
    return polymost2_compileShader(shaderType, source, &length);
510
}
511
 
584 terminx 512
void polymost_glreset()
5 Plagman 513
{
5829 terminx 514
    for (bssize_t i=0; i<=MAXPALOOKUPS-1; i++)
1220 terminx 515
    {
5349 hendricks2 516
        fogtable[i].r = palookupfog[i].r * (1.f/255.f);
517
        fogtable[i].g = palookupfog[i].g * (1.f/255.f);
518
        fogtable[i].b = palookupfog[i].b * (1.f/255.f);
5079 terminx 519
        fogtable[i].a = 0;
1220 terminx 520
    }
521
 
109 terminx 522
    //Reset if this is -1 (meaning 1st texture call ever), or > 0 (textures in memory)
523
    if (gltexcacnum < 0)
524
    {
525
        gltexcacnum = 0;
5 Plagman 526
 
109 terminx 527
        //Hack for polymost_dorotatesprite calls before 1st polymost_drawrooms()
4605 terminx 528
        gcosang = gcosang2 = 16384.f/262144.f;
5079 terminx 529
        gsinang = gsinang2 = 0.f;
109 terminx 530
    }
531
    else
532
    {
5829 terminx 533
        for (bssize_t i = 0; i <= GLTEXCACHEADSIZ-1; i++)
584 terminx 534
        {
5075 terminx 535
            for (pthtyp *pth = texcache.list[i]; pth;)
584 terminx 536
            {
5075 terminx 537
                pthtyp *const next = pth->next;
538
 
4486 helixhorne 539
                if (pth->flags & PTH_HASFULLBRIGHT)
248 terminx 540
                {
6656 pogokeen 541
                    glDeleteTextures(1, &pth->ofb->glpic);
7705 terminx 542
                    Xfree(pth->ofb);
248 terminx 543
                }
2639 helixhorne 544
 
6656 pogokeen 545
                glDeleteTextures(1, &pth->glpic);
7705 terminx 546
                Xfree(pth);
109 terminx 547
                pth = next;
548
            }
2639 helixhorne 549
 
3781 terminx 550
            texcache.list[i] = NULL;
109 terminx 551
        }
5075 terminx 552
 
5494 hendricks2 553
        clearskins(INVALIDATE_ALL);
109 terminx 554
    }
555
 
2639 helixhorne 556
    if (polymosttext)
6656 pogokeen 557
        glDeleteTextures(1,&polymosttext);
109 terminx 558
    polymosttext=0;
559
 
5526 hendricks2 560
#ifdef USE_GLEXT
4639 terminx 561
    md_freevbos();
5526 hendricks2 562
#endif
1317 terminx 563
 
4675 terminx 564
    Bmemset(texcache.list,0,sizeof(texcache.list));
109 terminx 565
    glox1 = -1;
446 Plagman 566
 
3758 terminx 567
    texcache_freeptrs();
5001 terminx 568
    texcache_syncmemcache();
1155 terminx 569
 
2014 helixhorne 570
#ifdef DEBUGGINGAIDS
571
    OSD_Printf("polymost_glreset()\n");
572
#endif
5 Plagman 573
}
574
 
5715 hendricks2 575
#if defined EDUKE32_GLES
576
static void Polymost_DetermineTextureFormatSupport(void);
577
#endif
2240 helixhorne 578
 
6652 pogokeen 579
// reset vertex pointers to polymost default
580
void polymost_resetVertexPointers()
581
{
7681 pogokeen 582
    polymost_outputGLDebugMessage(3, "polymost_resetVertexPointers()");
583
 
6662 pogokeen 584
    glBindBuffer(GL_ARRAY_BUFFER, drawpolyVertsID);
6700 hendricks2 585
 
6662 pogokeen 586
    glVertexPointer(3, GL_FLOAT, 5*sizeof(float), 0);
587
    glTexCoordPointer(2, GL_FLOAT, 5*sizeof(float), (GLvoid*) (3*sizeof(float)));
6700 hendricks2 588
 
6652 pogokeen 589
#ifdef USE_GLEXT
590
    if (r_detailmapping)
591
    {
6776 pogokeen 592
        glClientActiveTexture(GL_TEXTURE3);
6662 pogokeen 593
        glTexCoordPointer(2, GL_FLOAT, 5*sizeof(float), (GLvoid*) (3*sizeof(float)));
6652 pogokeen 594
    }
595
    if (r_glowmapping)
596
    {
6776 pogokeen 597
        glClientActiveTexture(GL_TEXTURE4);
6662 pogokeen 598
        glTexCoordPointer(2, GL_FLOAT, 5*sizeof(float), (GLvoid*) (3*sizeof(float)));
6652 pogokeen 599
    }
6656 pogokeen 600
    glClientActiveTexture(GL_TEXTURE0);
6652 pogokeen 601
#endif
6776 pogokeen 602
 
603
    polymost_resetProgram();
6652 pogokeen 604
}
605
 
6776 pogokeen 606
void polymost_disableProgram()
607
{
7419 terminx 608
    if (videoGetRenderMode() != REND_POLYMOST)
609
        return;
610
 
7681 pogokeen 611
    polymost_outputGLDebugMessage(3, "polymost_disableProgram()");
612
 
7419 terminx 613
    useShaderProgram(0);
6776 pogokeen 614
}
615
 
616
void polymost_resetProgram()
617
{
7419 terminx 618
    if (videoGetRenderMode() != REND_POLYMOST)
619
        return;
6777 pogokeen 620
 
7681 pogokeen 621
    polymost_outputGLDebugMessage(3, "polymost_resetProgram()");
622
 
7419 terminx 623
    if (r_enablepolymost2)
624
        useShaderProgram(polymost2BasicShaderProgramID);
625
    else
626
        useShaderProgram(polymost1CurrentShaderProgramID);
627
 
628
    // ensure that palswapTexture and paletteTexture[curbasepal] is bound
629
    glActiveTexture(GL_TEXTURE1);
630
    glBindTexture(GL_TEXTURE_2D, palswapTextureID);
631
    glActiveTexture(GL_TEXTURE2);
632
    glBindTexture(GL_TEXTURE_2D, paletteTextureIDs[curbasepal]);
633
    glActiveTexture(GL_TEXTURE0);
6776 pogokeen 634
}
635
 
636
static void polymost_setCurrentShaderProgram(uint32_t programID)
637
{
7681 pogokeen 638
    polymost_outputGLDebugMessage(3, "polymost_setCurrentShaderProgram(programID:%u)", programID);
639
 
6776 pogokeen 640
    polymost1CurrentShaderProgramID = programID;
641
    useShaderProgram(programID);
642
 
643
    //update the uniform locations
644
    polymost1TexSamplerLoc = glGetUniformLocation(polymost1CurrentShaderProgramID, "s_texture");
645
    polymost1PalSwapSamplerLoc = glGetUniformLocation(polymost1CurrentShaderProgramID, "s_palswap");
646
    polymost1PaletteSamplerLoc = glGetUniformLocation(polymost1CurrentShaderProgramID, "s_palette");
647
    polymost1DetailSamplerLoc = glGetUniformLocation(polymost1CurrentShaderProgramID, "s_detail");
648
    polymost1GlowSamplerLoc = glGetUniformLocation(polymost1CurrentShaderProgramID, "s_glow");
6883 pogokeen 649
    polymost1TexturePosSizeLoc = glGetUniformLocation(polymost1CurrentShaderProgramID, "u_texturePosSize");
650
    polymost1HalfTexelSizeLoc = glGetUniformLocation(polymost1CurrentShaderProgramID, "u_halfTexelSize");
6777 pogokeen 651
    polymost1PalswapPosLoc = glGetUniformLocation(polymost1CurrentShaderProgramID, "u_palswapPos");
652
    polymost1PalswapSizeLoc = glGetUniformLocation(polymost1CurrentShaderProgramID, "u_palswapSize");
7783 pogokeen 653
    polymost1ClampLoc = glGetUniformLocation(polymost1CurrentShaderProgramID, "u_clamp");
6776 pogokeen 654
    polymost1ShadeLoc = glGetUniformLocation(polymost1CurrentShaderProgramID, "u_shade");
7412 terminx 655
    polymost1NumShadesLoc = glGetUniformLocation(polymost1CurrentShaderProgramID, "u_numShades");
656
    polymost1VisFactorLoc = glGetUniformLocation(polymost1CurrentShaderProgramID, "u_visFactor");
6776 pogokeen 657
    polymost1FogEnabledLoc = glGetUniformLocation(polymost1CurrentShaderProgramID, "u_fogEnabled");
658
    polymost1UsePaletteLoc = glGetUniformLocation(polymost1CurrentShaderProgramID, "u_usePalette");
659
    polymost1UseColorOnlyLoc = glGetUniformLocation(polymost1CurrentShaderProgramID, "u_useColorOnly");
660
    polymost1UseDetailMappingLoc = glGetUniformLocation(polymost1CurrentShaderProgramID, "u_useDetailMapping");
661
    polymost1UseGlowMappingLoc = glGetUniformLocation(polymost1CurrentShaderProgramID, "u_useGlowMapping");
7413 terminx 662
    polymost1NPOTEmulationLoc = glGetUniformLocation(polymost1CurrentShaderProgramID, "u_npotEmulation");
663
    polymost1NPOTEmulationFactorLoc = glGetUniformLocation(polymost1CurrentShaderProgramID, "u_npotEmulationFactor");
664
    polymost1NPOTEmulationXOffsetLoc = glGetUniformLocation(polymost1CurrentShaderProgramID, "u_npotEmulationXOffset");
7412 terminx 665
    polymost1RotMatrixLoc = glGetUniformLocation(polymost1CurrentShaderProgramID, "u_rotMatrix");
7650 terminx 666
    polymost1ShadeInterpolateLoc = glGetUniformLocation(polymost1CurrentShaderProgramID, "u_shadeInterpolate");
6776 pogokeen 667
 
668
    //set the uniforms to the current values
6883 pogokeen 669
    glUniform4f(polymost1TexturePosSizeLoc, polymost1TexturePosSize.x, polymost1TexturePosSize.y, polymost1TexturePosSize.z, polymost1TexturePosSize.w);
670
    glUniform2f(polymost1HalfTexelSizeLoc, polymost1HalfTexelSize.x, polymost1HalfTexelSize.y);
6777 pogokeen 671
    glUniform2f(polymost1PalswapPosLoc, polymost1PalswapPos.x, polymost1PalswapPos.y);
672
    glUniform2f(polymost1PalswapSizeLoc, polymost1PalswapInnerSize.x, polymost1PalswapInnerSize.y);
7783 pogokeen 673
    glUniform1f(polymost1ClampLoc, polymost1Clamp);
6776 pogokeen 674
    glUniform1f(polymost1ShadeLoc, polymost1Shade);
7412 terminx 675
    glUniform1f(polymost1NumShadesLoc, polymost1NumShades);
676
    glUniform1f(polymost1VisFactorLoc, polymost1VisFactor);
6776 pogokeen 677
    glUniform1f(polymost1FogEnabledLoc, polymost1FogEnabled);
678
    glUniform1f(polymost1UseColorOnlyLoc, polymost1UseColorOnly);
679
    glUniform1f(polymost1UsePaletteLoc, polymost1UsePalette);
680
    glUniform1f(polymost1UseDetailMappingLoc, polymost1UseDetailMapping);
681
    glUniform1f(polymost1UseGlowMappingLoc, polymost1UseGlowMapping);
7413 terminx 682
    glUniform1f(polymost1NPOTEmulationLoc, polymost1NPOTEmulation);
683
    glUniform1f(polymost1NPOTEmulationFactorLoc, polymost1NPOTEmulationFactor);
684
    glUniform1f(polymost1NPOTEmulationXOffsetLoc, polymost1NPOTEmulationXOffset);
7412 terminx 685
    glUniformMatrix4fv(polymost1RotMatrixLoc, 1, false, polymost1RotMatrix);
7650 terminx 686
    glUniform1f(polymost1ShadeInterpolateLoc, polymost1ShadeInterpolate);
6776 pogokeen 687
}
688
 
7085 terminx 689
void polymost_setTexturePosSize(vec4f_t const &texturePosSize)
6883 pogokeen 690
{
7419 terminx 691
    if (currentShaderProgramID != polymost1CurrentShaderProgramID)
692
        return;
693
 
694
    polymost1TexturePosSize = texturePosSize;
695
    glUniform4f(polymost1TexturePosSizeLoc, polymost1TexturePosSize.x, polymost1TexturePosSize.y, polymost1TexturePosSize.z, polymost1TexturePosSize.w);
6883 pogokeen 696
}
697
 
7458 terminx 698
void polymost_setHalfTexelSize(vec2f_t const &halfTexelSize)
6883 pogokeen 699
{
7419 terminx 700
    if (currentShaderProgramID != polymost1CurrentShaderProgramID || (halfTexelSize.x == polymost1HalfTexelSize.x && halfTexelSize.y == polymost1HalfTexelSize.y))
701
        return;
702
 
703
    polymost1HalfTexelSize = halfTexelSize;
704
    glUniform2f(polymost1HalfTexelSizeLoc, polymost1HalfTexelSize.x, polymost1HalfTexelSize.y);
6883 pogokeen 705
}
706
 
6777 pogokeen 707
static void polymost_setPalswap(uint32_t index)
708
{
7419 terminx 709
    static uint32_t lastPalswapIndex;
6777 pogokeen 710
 
7419 terminx 711
    if (currentShaderProgramID != polymost1CurrentShaderProgramID || index == lastPalswapIndex)
712
        return;
713
 
714
    lastPalswapIndex = index;
715
    polymost1PalswapPos.x = index*polymost1PalswapSize.x;
716
    polymost1PalswapPos.y = floorf(polymost1PalswapPos.x);
7434 terminx 717
    polymost1PalswapPos = { polymost1PalswapPos.x - polymost1PalswapPos.y + (0.5f/PALSWAP_TEXTURE_SIZE),
718
                            polymost1PalswapPos.y * polymost1PalswapSize.y + (0.5f/PALSWAP_TEXTURE_SIZE) };
7419 terminx 719
    glUniform2f(polymost1PalswapPosLoc, polymost1PalswapPos.x, polymost1PalswapPos.y);
6777 pogokeen 720
}
721
 
722
static void polymost_setPalswapSize(uint32_t width, uint32_t height)
723
{
7419 terminx 724
    if (currentShaderProgramID != polymost1CurrentShaderProgramID)
725
        return;
726
 
7434 terminx 727
    polymost1PalswapSize = { width*(1.f/PALSWAP_TEXTURE_SIZE),
728
                             height*(1.f/PALSWAP_TEXTURE_SIZE) };
729
 
730
    polymost1PalswapInnerSize = { (width-1)*(1.f/PALSWAP_TEXTURE_SIZE),
731
                                  (height-1)*(1.f/PALSWAP_TEXTURE_SIZE) };
732
 
7419 terminx 733
    glUniform2f(polymost1PalswapSizeLoc, polymost1PalswapInnerSize.x, polymost1PalswapInnerSize.y);
6777 pogokeen 734
}
735
 
7783 pogokeen 736
char polymost_getClamp()
737
{
738
    return polymost1Clamp;
739
}
740
 
741
void polymost_setClamp(char clamp)
742
{
743
    if (currentShaderProgramID != polymost1CurrentShaderProgramID ||
744
        clamp == polymost1Clamp)
745
        return;
746
 
747
    polymost1Clamp = clamp;
748
    glUniform1f(polymost1ClampLoc, polymost1Clamp);
749
}
750
 
6777 pogokeen 751
static void polymost_setShade(int32_t shade)
752
{
7419 terminx 753
    if (currentShaderProgramID != polymost1CurrentShaderProgramID)
754
        return;
755
 
7420 terminx 756
    if (globalflags & GLOBAL_NO_GL_TILESHADES)
7419 terminx 757
        shade = 0;
758
 
759
    static int32_t lastShade;
760
    static int32_t lastNumShades;
761
 
762
    if (shade != lastShade)
6777 pogokeen 763
    {
7419 terminx 764
        lastShade = shade;
765
        polymost1Shade = shade;
766
        glUniform1f(polymost1ShadeLoc, polymost1Shade);
767
    }
6936 pogokeen 768
 
7419 terminx 769
    if (numshades != lastNumShades)
770
    {
771
        lastNumShades = numshades;
772
        polymost1NumShades = numshades;
773
        glUniform1f(polymost1NumShadesLoc, polymost1NumShades);
7412 terminx 774
    }
775
}
6777 pogokeen 776
 
7458 terminx 777
void polymost_setVisibility(float visibility)
7412 terminx 778
{
7419 terminx 779
    if (currentShaderProgramID != polymost1CurrentShaderProgramID)
780
        return;
781
 
7737 pogokeen 782
    float visFactor = visibility * fviewingrange * (1.f / (64.f * 65536.f));
783
    if (visFactor == polymost1VisFactor)
784
        return;
785
 
786
    polymost1VisFactor = visFactor;
7419 terminx 787
    glUniform1f(polymost1VisFactorLoc, polymost1VisFactor);
6777 pogokeen 788
}
789
 
6776 pogokeen 790
void polymost_setFogEnabled(char fogEnabled)
791
{
7419 terminx 792
    if (currentShaderProgramID != polymost1CurrentShaderProgramID || fogEnabled == polymost1FogEnabled)
793
        return;
794
 
795
    polymost1FogEnabled = fogEnabled;
796
    glUniform1f(polymost1FogEnabledLoc, polymost1FogEnabled);
6776 pogokeen 797
}
798
 
799
void polymost_useColorOnly(char useColorOnly)
800
{
7419 terminx 801
    if (currentShaderProgramID != polymost1CurrentShaderProgramID || useColorOnly == polymost1UseColorOnly)
802
        return;
803
 
804
    polymost1UseColorOnly = useColorOnly;
805
    glUniform1f(polymost1UseColorOnlyLoc, polymost1UseColorOnly);
6776 pogokeen 806
}
807
 
808
void polymost_usePaletteIndexing(char usePaletteIndexing)
809
{
7419 terminx 810
    if (currentShaderProgramID != polymost1CurrentShaderProgramID || usePaletteIndexing == polymost1UsePalette)
811
        return;
812
 
813
    polymost1UsePalette = usePaletteIndexing;
814
    glUniform1f(polymost1UsePaletteLoc, polymost1UsePalette);
6776 pogokeen 815
}
816
 
817
void polymost_useDetailMapping(char useDetailMapping)
818
{
7419 terminx 819
    if (currentShaderProgramID != polymost1CurrentShaderProgramID || useDetailMapping == polymost1UseDetailMapping)
820
        return;
6777 pogokeen 821
 
7419 terminx 822
    if (useDetailMapping)
823
        polymost_setCurrentShaderProgram(polymost1ExtendedShaderProgramID);
6776 pogokeen 824
 
7419 terminx 825
    polymost1UseDetailMapping = useDetailMapping;
826
    glUniform1f(polymost1UseDetailMappingLoc, polymost1UseDetailMapping);
6776 pogokeen 827
}
828
 
829
void polymost_useGlowMapping(char useGlowMapping)
830
{
7419 terminx 831
    if (currentShaderProgramID != polymost1CurrentShaderProgramID || useGlowMapping == polymost1UseGlowMapping)
832
        return;
6777 pogokeen 833
 
7419 terminx 834
    if (useGlowMapping)
835
        polymost_setCurrentShaderProgram(polymost1ExtendedShaderProgramID);
6776 pogokeen 836
 
7419 terminx 837
    polymost1UseGlowMapping = useGlowMapping;
838
    glUniform1f(polymost1UseGlowMappingLoc, polymost1UseGlowMapping);
6776 pogokeen 839
}
840
 
7413 terminx 841
void polymost_npotEmulation(char npotEmulation, float factor, float xOffset)
842
{
7419 terminx 843
    if (currentShaderProgramID != polymost1CurrentShaderProgramID || npotEmulation == polymost1NPOTEmulation)
844
        return;
845
 
846
    polymost1NPOTEmulation = npotEmulation;
847
    glUniform1f(polymost1NPOTEmulationLoc, polymost1NPOTEmulation);
848
    polymost1NPOTEmulationFactor = factor;
849
    glUniform1f(polymost1NPOTEmulationFactorLoc, polymost1NPOTEmulationFactor);
850
    polymost1NPOTEmulationXOffset = xOffset;
851
    glUniform1f(polymost1NPOTEmulationXOffsetLoc, polymost1NPOTEmulationXOffset);
7413 terminx 852
}
853
 
7650 terminx 854
void polymost_shadeInterpolate(int32_t shadeInterpolate)
855
{
856
    if (currentShaderProgramID == polymost1CurrentShaderProgramID)
857
    {
858
        polymost1ShadeInterpolate = shadeInterpolate;
859
        glUniform1f(polymost1ShadeInterpolateLoc, polymost1ShadeInterpolate);
860
    }
861
}
862
 
6883 pogokeen 863
void polymost_activeTexture(GLenum texture)
864
{
865
    currentActiveTexture = texture;
866
    glad_glActiveTexture(texture);
867
}
868
 
869
//POGOTODO: replace this and polymost_activeTexture with proper draw call organization
870
void polymost_bindTexture(GLenum target, uint32_t textureID)
871
{
872
    if (currentTextureID != textureID ||
873
        textureID == 0 ||
874
        currentActiveTexture != GL_TEXTURE0 ||
875
        videoGetRenderMode() != REND_POLYMOST)
876
    {
877
        glad_glBindTexture(target, textureID);
878
        if (currentActiveTexture == GL_TEXTURE0)
879
        {
880
            currentTextureID = textureID;
881
        }
882
    }
883
}
884
 
7109 terminx 885
static void polymost_bindPth(pthtyp const * const pPth)
6883 pogokeen 886
{
7041 terminx 887
    Bassert(pPth);
888
 
6883 pogokeen 889
    vec4f_t texturePosSize = { 0.f, 0.f, 1.f, 1.f };
890
    vec2f_t halfTexelSize = { 0.f, 0.f };
6885 pogokeen 891
    if ((pPth->flags & PTH_INDEXED) &&
6883 pogokeen 892
        !(pPth->flags & PTH_HIGHTILE))
893
    {
894
        Tile tile;
895
        char tileIsPacked = tilepacker_getTile(waloff[pPth->picnum] ? pPth->picnum+1 : 0, &tile);
896
        //POGO: check the width and height to ensure that the tile hasn't been changed for a user tile that has different dimensions
897
        if (tileIsPacked &&
898
            (!waloff[pPth->picnum] ||
899
             (tile.rect.width == (uint32_t) tilesiz[pPth->picnum].y &&
900
              tile.rect.height == (uint32_t) tilesiz[pPth->picnum].x)))
901
        {
902
            texturePosSize = { tile.rect.u/(float) tilesheetSize,
903
                               tile.rect.v/(float) tilesheetSize,
904
                               tile.rect.width/(float) tilesheetSize,
905
                               tile.rect.height/(float) tilesheetSize };
906
            halfTexelSize = tilesheetHalfTexelSize;
907
        }
908
    }
909
    polymost_setTexturePosSize(texturePosSize);
910
    polymost_setHalfTexelSize(halfTexelSize);
911
    glBindTexture(GL_TEXTURE_2D, pPth->glpic);
912
}
913
 
6776 pogokeen 914
void useShaderProgram(uint32_t shaderID)
915
{
916
    glUseProgram(shaderID);
917
    currentShaderProgramID = shaderID;
918
}
919
 
627 terminx 920
// one-time initialization of OpenGL for polymost
5 Plagman 921
void polymost_glinit()
922
{
6656 pogokeen 923
    glHint(GL_FOG_HINT, GL_NICEST);
924
    glFogi(GL_FOG_MODE, (r_usenewshading < 2) ? GL_EXP2 : GL_LINEAR);
925
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
109 terminx 926
 
6656 pogokeen 927
    glPixelStorei(GL_PACK_ALIGNMENT, 1);
928
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
2579 plagman 929
 
7754 pogokeen 930
    if (glinfo.depthclamp)
931
        glEnable(GL_DEPTH_CLAMP);
932
 
6656 pogokeen 933
    //glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
934
    //glEnable(GL_LINE_SMOOTH);
6700 hendricks2 935
 
6776 pogokeen 936
    if (r_useindexedcolortextures == -1)
937
    {
938
        //POGO: r_useindexedcolortextures has never been set, so force it to be enabled
939
        gltexfiltermode = 0;
940
    }
941
 
6662 pogokeen 942
#ifdef USE_GLEXT
943
    if (glmultisample > 0 && glinfo.multisample)
944
    {
945
        if (glinfo.nvmultisamplehint)
946
            glHint(GL_MULTISAMPLE_FILTER_HINT_NV, glnvmultisamplehint ? GL_NICEST:GL_FASTEST);
947
        glEnable(GL_MULTISAMPLE);
948
    }
118 terminx 949
 
7048 pogokeen 950
    if (r_persistentStreamBuffer && ((!glinfo.bufferstorage) || (!glinfo.sync)))
6662 pogokeen 951
    {
952
        OSD_Printf("Your OpenGL implementation doesn't support the required extensions for persistent stream buffers. Disabling...\n");
6669 pogokeen 953
        r_persistentStreamBuffer = 0;
6662 pogokeen 954
    }
955
#endif
6700 hendricks2 956
 
6883 pogokeen 957
    //POGOTODO: require a max texture size >= 2048
958
 
6662 pogokeen 959
    persistentStreamBuffer = r_persistentStreamBuffer;
960
    drawpolyVertsBufferLength = r_drawpolyVertsBufferLength;
6700 hendricks2 961
 
6662 pogokeen 962
    drawpolyVertsOffset = 0;
963
    drawpolyVertsSubBufferIndex = 0;
6700 hendricks2 964
 
6662 pogokeen 965
    GLuint ids[2];
966
    glGenBuffers(2, ids);
967
    drawpolyVertsID = ids[0];
968
    glBindBuffer(GL_ARRAY_BUFFER, drawpolyVertsID);
969
    if (persistentStreamBuffer)
970
    {
971
        // reset the sync objects, as old ones we had from any last GL context are gone now
972
        Bmemset(drawpolyVertsSync, 0, sizeof(drawpolyVertsSync));
6700 hendricks2 973
 
6662 pogokeen 974
        GLbitfield flags = GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT;
975
        // we want to triple-buffer to avoid having to wait for the buffer to become available again,
976
        // so triple the buffer size we expect to use
977
        glBufferStorage(GL_ARRAY_BUFFER, 3*drawpolyVertsBufferLength*sizeof(float)*5, NULL, flags);
978
        drawpolyVerts = (float*) glMapBufferRange(GL_ARRAY_BUFFER, 0, 3*drawpolyVertsBufferLength*sizeof(float)*5, flags);
6776 pogokeen 979
    }
980
    else
6662 pogokeen 981
    {
982
        drawpolyVerts = defaultDrawpolyVertsArray;
983
        glBufferData(GL_ARRAY_BUFFER, drawpolyVertsBufferLength*sizeof(float)*5, NULL, GL_STREAM_DRAW);
984
    }
985
    glBindBuffer(GL_ARRAY_BUFFER, 0);
6700 hendricks2 986
 
6883 pogokeen 987
    currentTextureID = 0;
6700 hendricks2 988
 
6883 pogokeen 989
    glGetIntegerv(GL_MAX_TEXTURE_SIZE, &tilesheetSize);
7414 terminx 990
#ifdef _MSC_VER
991
    if (tilesheetSize > 8192)
992
        tilesheetSize = 8192;
993
#endif
6883 pogokeen 994
    tilesheetHalfTexelSize = { 0.5f/tilesheetSize, 0.5f/tilesheetSize };
995
    vec2_t maxTexDimensions = { tilesheetSize, tilesheetSize };
996
    char allPacked = false;
7673 terminx 997
    static int numTilesheets = 0;
6883 pogokeen 998
    //POGO: only pack the tilesheets once
999
    if (numTilesheets == 0)
1000
    {
1001
        // add a blank texture for tileUID 0
1002
        tilepacker_addTile(0, 2, 2);
1003
        for (int picnum = 0; picnum < MAXTILES; ++picnum)
1004
        {
1005
            tilepacker_addTile(picnum+1, (uint32_t) tilesiz[picnum].y, (uint32_t) tilesiz[picnum].x);
1006
        }
1007
 
1008
        do
1009
        {
1010
            tilepacker_initTilesheet(numTilesheets, tilesheetSize, tilesheetSize);
1011
            allPacked = tilepacker_pack(numTilesheets);
1012
            ++numTilesheets;
1013
        } while (!allPacked && numTilesheets < MAXTILESHEETS);
1014
    }
7673 terminx 1015
    for (int i = 0; i < numTilesheets; ++i)
6883 pogokeen 1016
    {
1017
        glGenTextures(1, tilesheetTexIDs+i);
1018
        glBindTexture(GL_TEXTURE_2D, tilesheetTexIDs[i]);
1019
        uploadtextureindexed(true, {0, 0}, maxTexDimensions, (intptr_t) NULL);
1020
    }
1021
 
1022
    const char blankTex[] = {255, 255,
1023
                             255, 255};
1024
    Tile blankTile;
1025
    tilepacker_getTile(0, &blankTile);
1026
    glBindTexture(GL_TEXTURE_2D, tilesheetTexIDs[blankTile.tilesheetID]);
1027
    uploadtextureindexed(false, {(int32_t) blankTile.rect.u, (int32_t) blankTile.rect.v}, {2, 2}, (intptr_t) blankTex);
1028
 
6662 pogokeen 1029
    quadVertsID = ids[1];
6658 pogokeen 1030
    glBindBuffer(GL_ARRAY_BUFFER, quadVertsID);
6700 hendricks2 1031
    const float quadVerts[] =
6658 pogokeen 1032
        {
1033
            -0.5f, 1.0f, 0.0f, 0.0f, 1.0f, //top-left
1034
            -0.5f, 0.0f, 0.0f, 0.0f, 0.0f, //bottom-left
1035
             0.5f, 1.0f, 0.0f, 1.0f, 1.0f, //top-right
1036
             0.5f, 0.0f, 0.0f, 1.0f, 0.0f  //bottom-right
1037
        };
1038
    glBufferData(GL_ARRAY_BUFFER, sizeof(quadVerts), quadVerts, GL_STATIC_DRAW);
6700 hendricks2 1039
 
6658 pogokeen 1040
    //specify format/arrangement for vertex positions:
1041
    glVertexAttribPointer(0, 3, GL_FLOAT, false, sizeof(float) * 5, 0);
1042
    //specify format/arrangement for vertex texture coords:
1043
    glVertexAttribPointer(1, 2, GL_FLOAT, false, sizeof(float) * 5, (const void*) (sizeof(float) * 3));
6700 hendricks2 1044
 
6658 pogokeen 1045
    glBindBuffer(GL_ARRAY_BUFFER, 0);
6700 hendricks2 1046
 
6776 pogokeen 1047
    const char* const POLYMOST2_BASIC_VERTEX_SHADER_CODE =
6658 pogokeen 1048
        "#version 110\n\
1049
         \n\
1050
         // input\n\
1051
         attribute vec3 i_vertPos;\n\
1052
         attribute vec2 i_texCoord;\n\
1053
         uniform mat4 u_mvMatrix;\n\
1054
         uniform mat4 u_projMatrix;\n\
1055
         uniform vec2 u_texOffset;\n\
1056
         uniform vec2 u_texScale;\n\
1057
         \n\
1058
         // output\n\
1059
         varying vec2 v_texCoord;\n\
1060
         varying float v_distance;\n\
1061
         \n\
1062
         void main()\n\
1063
         {\n\
1064
            vec4 eyeCoordPosition = u_mvMatrix * vec4(i_vertPos, 1.0);\n\
1065
            gl_Position = u_projMatrix * eyeCoordPosition;\n\
1066
            \n\
1067
            eyeCoordPosition.xyz /= eyeCoordPosition.w;\n\
1068
            \n\
1069
            v_texCoord = i_texCoord * u_texScale + u_texOffset;\n\
1070
            v_distance = eyeCoordPosition.z;\n\
1071
         }\n";
6776 pogokeen 1072
    const char* const POLYMOST2_BASIC_FRAGMENT_SHADER_CODE =
6658 pogokeen 1073
        "#version 110\n\
1074
         \n\
1075
         varying vec2 v_texCoord;\n\
1076
         uniform sampler2D s_texture;\n\
1077
         uniform sampler2D s_fullBright;\n\
1078
         \n\
1079
         uniform vec4 u_tint;\n\
1080
         uniform float u_alpha;\n\
1081
         \n\
1082
         varying float v_distance;\n\
1083
         uniform vec2 u_fogRange;\n\
1084
         uniform vec4 u_fogColor;\n\
1085
         \n\
1086
         const float c_zero = 0.0;\n\
1087
         const float c_one  = 1.0;\n\
1088
         \n\
1089
         void main()\n\
1090
         {\n\
1091
             vec4 color = texture2D(s_texture, v_texCoord);\n\
1092
             vec4 fullBrightColor = texture2D(s_fullBright, v_texCoord);\n\
1093
             \n\
1094
             float fogFactor = clamp((u_fogRange.y-v_distance)/(u_fogRange.y-u_fogRange.x), c_zero, c_one);\n\
1095
             \n\
1096
             color.rgb = mix(u_fogColor.rgb, color.rgb, fogFactor);\n\
1097
             color.rgb *= u_tint.rgb * u_tint.a * color.a;\n\
1098
             color.rgb = mix(color.rgb, fullBrightColor.rgb, fullBrightColor.a);\n\
1099
             \n\
1100
             color.a *= u_alpha;\n\
1101
             \n\
1102
             gl_FragColor = color;\n\
1103
         }\n";
6700 hendricks2 1104
 
6776 pogokeen 1105
    polymost2BasicShaderProgramID = glCreateProgram();
7787 hendricks2 1106
    GLuint polymost2BasicVertexShaderID = polymost2_compileShader(GL_VERTEX_SHADER, POLYMOST2_BASIC_VERTEX_SHADER_CODE);
1107
    GLuint polymost2BasicFragmentShaderID = polymost2_compileShader(GL_FRAGMENT_SHADER, POLYMOST2_BASIC_FRAGMENT_SHADER_CODE);
6776 pogokeen 1108
    glBindAttribLocation(polymost2BasicShaderProgramID, 0, "i_vertPos");
1109
    glBindAttribLocation(polymost2BasicShaderProgramID, 1, "i_texCoord");
1110
    glAttachShader(polymost2BasicShaderProgramID, polymost2BasicVertexShaderID);
1111
    glAttachShader(polymost2BasicShaderProgramID, polymost2BasicFragmentShaderID);
1112
    glLinkProgram(polymost2BasicShaderProgramID);
6700 hendricks2 1113
 
6658 pogokeen 1114
    // Get the attribute/uniform locations
6776 pogokeen 1115
    texSamplerLoc = glGetUniformLocation(polymost2BasicShaderProgramID, "s_texture");
1116
    fullBrightSamplerLoc = glGetUniformLocation(polymost2BasicShaderProgramID, "s_fullBright");
1117
    projMatrixLoc = glGetUniformLocation(polymost2BasicShaderProgramID, "u_projMatrix");
1118
    mvMatrixLoc = glGetUniformLocation(polymost2BasicShaderProgramID, "u_mvMatrix");
1119
    texOffsetLoc = glGetUniformLocation(polymost2BasicShaderProgramID, "u_texOffset");
1120
    texScaleLoc = glGetUniformLocation(polymost2BasicShaderProgramID, "u_texScale");
1121
    tintLoc = glGetUniformLocation(polymost2BasicShaderProgramID, "u_tint");
1122
    alphaLoc = glGetUniformLocation(polymost2BasicShaderProgramID, "u_alpha");
1123
    fogRangeLoc = glGetUniformLocation(polymost2BasicShaderProgramID, "u_fogRange");
1124
    fogColorLoc = glGetUniformLocation(polymost2BasicShaderProgramID, "u_fogColor");
439 Plagman 1125
 
7782 pogokeen 1126
    polymost1ExtendedShaderProgramID = glCreateProgram();
7787 hendricks2 1127
    GLuint polymost1BasicVertexShaderID = polymost2_compileShader(GL_VERTEX_SHADER, polymost1Vert);
1128
    GLuint polymost1ExtendedFragmentShaderID = polymost2_compileShader(GL_FRAGMENT_SHADER, polymost1Frag);
7782 pogokeen 1129
    glAttachShader(polymost1ExtendedShaderProgramID, polymost1BasicVertexShaderID);
1130
    glAttachShader(polymost1ExtendedShaderProgramID, polymost1ExtendedFragmentShaderID);
1131
    glLinkProgram(polymost1ExtendedShaderProgramID);
1132
 
1133
    int polymost1BasicFragLen = strlen(polymost1Frag);
1134
    char* polymost1BasicFrag = (char*) malloc(polymost1BasicFragLen);
1135
    memcpy(polymost1BasicFrag, polymost1Frag, polymost1BasicFragLen);
1136
    char* extDefineSubstr = strstr(polymost1BasicFrag, " #define POLYMOST1_EXTENDED");
1137
    if (extDefineSubstr)
1138
    {
1139
        //Disable extensions for basic fragment shader
1140
        extDefineSubstr[0] = '/';
1141
        extDefineSubstr[1] = '/';
1142
    }
6776 pogokeen 1143
    polymost1BasicShaderProgramID = glCreateProgram();
7782 pogokeen 1144
    GLuint polymost1BasicFragmentShaderID = polymost2_compileShader(GL_FRAGMENT_SHADER, polymost1BasicFrag, polymost1BasicFragLen);
6776 pogokeen 1145
    glAttachShader(polymost1BasicShaderProgramID, polymost1BasicVertexShaderID);
1146
    glAttachShader(polymost1BasicShaderProgramID, polymost1BasicFragmentShaderID);
1147
    glLinkProgram(polymost1BasicShaderProgramID);
7782 pogokeen 1148
    free(polymost1BasicFrag);
1149
    polymost1BasicFrag = 0;
6776 pogokeen 1150
 
1151
    // set defaults
1152
    polymost_setCurrentShaderProgram(polymost1ExtendedShaderProgramID);
1153
    glUniform1i(polymost1TexSamplerLoc, 0);
1154
    glUniform1i(polymost1PalSwapSamplerLoc, 1);
1155
    glUniform1i(polymost1PaletteSamplerLoc, 2);
1156
    glUniform1i(polymost1DetailSamplerLoc, 3);
1157
    glUniform1i(polymost1GlowSamplerLoc, 4);
6777 pogokeen 1158
    polymost_setPalswapSize(256, numshades+1);
6776 pogokeen 1159
    polymost_setCurrentShaderProgram(polymost1BasicShaderProgramID);
1160
    glUniform1i(polymost1TexSamplerLoc, 0);
1161
    glUniform1i(polymost1PalSwapSamplerLoc, 1);
1162
    glUniform1i(polymost1PaletteSamplerLoc, 2);
1163
    useShaderProgram(0);
1164
 
1165
    lastbasepal = -1;
1166
    for (int basepalnum = 0; basepalnum < MAXBASEPALS; ++basepalnum)
1167
    {
1168
        paletteTextureIDs[basepalnum] = 0;
1169
        uploadbasepalette(basepalnum);
1170
    }
6777 pogokeen 1171
    palswapTextureID = 0;
6776 pogokeen 1172
    for (int palookupnum = 0; palookupnum < MAXPALOOKUPS; ++palookupnum)
1173
    {
1174
        uploadpalswap(palookupnum);
1175
    }
1176
 
6656 pogokeen 1177
    glEnableClientState(GL_VERTEX_ARRAY);
1178
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
6700 hendricks2 1179
 
6652 pogokeen 1180
    polymost_resetVertexPointers();
1155 terminx 1181
 
3758 terminx 1182
    texcache_init();
1183
    texcache_loadoffsets();
3761 terminx 1184
    texcache_openfiles();
5768 hendricks2 1185
 
3761 terminx 1186
    texcache_setupmemcache();
1187
    texcache_checkgarbage();
5704 hendricks2 1188
 
5715 hendricks2 1189
#if defined EDUKE32_GLES
1190
    Polymost_DetermineTextureFormatSupport();
1191
#endif
5 Plagman 1192
}
1193
 
6776 pogokeen 1194
void polymost_init()
1195
{
1196
    lastbasepal = -1;
1197
    polymost_resetVertexPointers();
1198
}
1199
 
3303 helixhorne 1200
////////// VISIBILITY FOG ROUTINES //////////
1201
 
4393 helixhorne 1202
// only for r_usenewshading < 2 (not preferred)
3768 terminx 1203
static void fogcalc_old(int32_t shade, int32_t vis)
3763 terminx 1204
{
1205
    float f;
1206
 
7103 terminx 1207
    if (r_usenewshading == 1)
3763 terminx 1208
    {
1209
        f = 0.9f * shade;
7103 terminx 1210
        f = (vis > 239) ? (float)(gvisibility * (vis - 240 + f)) :
1211
                          (float)(gvisibility * (vis + 16 + f));
3763 terminx 1212
    }
1213
    else
1214
    {
1215
        f = (shade < 0) ? shade * 3.5f : shade * .66f;
7103 terminx 1216
        f = (vis > 239) ? (float)(gvisibility * ((vis - 240 + f) / (klabs(vis - 256)))) :
1217
                          (float)(gvisibility * (vis + 16 + f));
3763 terminx 1218
    }
1219
 
7103 terminx 1220
    fogresult = clamp(f, 0.001f, 100.0f);
3763 terminx 1221
}
1222
 
3303 helixhorne 1223
// For GL_LINEAR fog:
3307 helixhorne 1224
#define FOGDISTCONST 600
5540 terminx 1225
#define FULLVIS_BEGIN 2.9e30f
1226
#define FULLVIS_END 3.0e30f
3303 helixhorne 1227
 
7424 terminx 1228
static inline void fogcalc(int32_t shade, int32_t vis, int32_t pal)
3303 helixhorne 1229
{
5079 terminx 1230
    fogcol = fogtable[pal];
4904 terminx 1231
 
4393 helixhorne 1232
    if (r_usenewshading < 2)
5075 terminx 1233
    {
3768 terminx 1234
        fogcalc_old(shade, vis);
5075 terminx 1235
        return;
1236
    }
1237
 
1238
    float combvis = (float) globalvisibility * (uint8_t) (vis+16);
1239
 
7424 terminx 1240
    if (combvis == 0.f)
3763 terminx 1241
    {
5075 terminx 1242
        if (r_usenewshading == 2 && shade > 0)
3303 helixhorne 1243
        {
5075 terminx 1244
            // beg = -D*shade, end = D*(NUMSHADES-1-shade)
1245
            //  => end/beg = -(NUMSHADES-1-shade)/shade
7103 terminx 1246
            fogresult = -FULLVIS_BEGIN;
1247
            fogresult2 = FULLVIS_BEGIN * (float)(numshades-1-shade) / shade;
3303 helixhorne 1248
        }
4452 helixhorne 1249
        else
1250
        {
7103 terminx 1251
            fogresult  = FULLVIS_BEGIN;
1252
            fogresult2 = FULLVIS_END;
4452 helixhorne 1253
        }
3303 helixhorne 1254
    }
5075 terminx 1255
    else if (r_usenewshading == 3 && shade >= numshades-1)
1256
    {
1257
        fogresult = -1;
1258
        fogresult2 = 0;
1259
    }
1260
    else
1261
    {
1262
        combvis = 1.f/combvis;
7103 terminx 1263
        fogresult = (r_usenewshading == 3 && shade > 0) ? 0.f : -(FOGDISTCONST * shade) * combvis;
5075 terminx 1264
        fogresult2 = (FOGDISTCONST * (numshades-1-shade)) * combvis;
1265
    }
3763 terminx 1266
}
3303 helixhorne 1267
 
6515 hendricks2 1268
#define GL_FOG_MAX 1.0e37f
1269
 
6658 pogokeen 1270
void polymost2_calc_fog(int32_t shade, int32_t vis, int32_t pal)
1271
{
1272
    if (nofog) return;
6700 hendricks2 1273
 
6658 pogokeen 1274
    fogcol = fogtable[pal];
6700 hendricks2 1275
 
6658 pogokeen 1276
    if (((uint8_t)(vis + 16)) > 0 && g_visibility > 0)
1277
    {
6961 hendricks2 1278
        constexpr GLfloat glfogconstant = 262144.f;
6658 pogokeen 1279
        GLfloat fogrange = (frealmaxshade * glfogconstant) / (((uint8_t)(vis + 16)) * globalvisibility);
1280
 
7712 terminx 1281
        fogresult = 0.f - (((min(shade, 0) - 0.5f) / frealmaxshade) * fogrange); // min() = subtract shades from fog
1282
        fogresult2 = fogrange - (((shade - 0.5f) / frealmaxshade) * fogrange);
6658 pogokeen 1283
    }
6961 hendricks2 1284
    else
7712 terminx 1285
    {
1286
        fogresult = 0.f;
6961 hendricks2 1287
        fogresult2 = -GL_FOG_MAX; // hide fog behind the camera
7712 terminx 1288
    }
6658 pogokeen 1289
}
1290
 
7424 terminx 1291
void calc_and_apply_fog(int32_t shade, int32_t vis, int32_t pal)
3763 terminx 1292
{
5699 terminx 1293
    if (nofog) return;
1294
 
6515 hendricks2 1295
    if (r_usenewshading == 4)
1296
    {
1297
        fogresult = 0.f;
1298
        fogcol = fogtable[pal];
1299
 
6590 hendricks2 1300
        if (((uint8_t)(vis + 16)) > 0 && globalvisibility > 0)
6515 hendricks2 1301
        {
6961 hendricks2 1302
            constexpr GLfloat glfogconstant = 262144.f;
6515 hendricks2 1303
            GLfloat fogrange = (frealmaxshade * glfogconstant) / (((uint8_t)(vis + 16)) * globalvisibility);
1304
 
7712 terminx 1305
            fogresult = 0.f - (((min(shade, 0) - 0.5f) / frealmaxshade) * fogrange); // min() = subtract shades from fog
1306
            fogresult2 = fogrange - (((shade - 0.5f) / frealmaxshade) * fogrange);
6515 hendricks2 1307
        }
6961 hendricks2 1308
        else
7712 terminx 1309
        {
1310
            fogresult = 0.f;
6961 hendricks2 1311
            fogresult2 = -GL_FOG_MAX; // hide fog behind the camera
7712 terminx 1312
        }
6515 hendricks2 1313
 
6656 pogokeen 1314
        glFogf(GL_FOG_START, fogresult);
1315
        glFogf(GL_FOG_END, fogresult2);
1316
        glFogfv(GL_FOG_COLOR, (GLfloat *)&fogcol);
6515 hendricks2 1317
 
1318
        return;
1319
    }
1320
 
7424 terminx 1321
    fogcalc(shade, vis, pal);
6656 pogokeen 1322
    glFogfv(GL_FOG_COLOR, (GLfloat *)&fogcol);
3303 helixhorne 1323
 
4393 helixhorne 1324
    if (r_usenewshading < 2)
6656 pogokeen 1325
        glFogf(GL_FOG_DENSITY, fogresult);
4904 terminx 1326
    else
3763 terminx 1327
    {
6656 pogokeen 1328
        glFogf(GL_FOG_START, fogresult);
1329
        glFogf(GL_FOG_END, fogresult2);
3763 terminx 1330
    }
3303 helixhorne 1331
}
1332
 
7424 terminx 1333
void calc_and_apply_fog_factor(int32_t shade, int32_t vis, int32_t pal, float factor)
3303 helixhorne 1334
{
5699 terminx 1335
    if (nofog) return;
1336
 
6515 hendricks2 1337
    if (r_usenewshading == 4)
1338
    {
1339
        fogcol = fogtable[pal];
1340
 
1341
        if (((uint8_t)(vis + 16)) > 0 && ((((uint8_t)(vis + 16)) / 8.f) + shade) > 0)
1342
        {
7712 terminx 1343
            GLfloat normalizedshade = (shade - 0.5f) / frealmaxshade;
6515 hendricks2 1344
            GLfloat fogrange = (((uint8_t)(vis + 16)) / (8.f * frealmaxshade)) + normalizedshade;
1345
 
6961 hendricks2 1346
            // subtract shades from fog
7712 terminx 1347
            if (normalizedshade > 0.f && normalizedshade < 1.f)
6515 hendricks2 1348
                fogrange = (fogrange - normalizedshade) / (1.f - normalizedshade);
1349
 
1350
            fogresult = -(GL_FOG_MAX * fogrange);
1351
            fogresult2 = GL_FOG_MAX - (GL_FOG_MAX * fogrange);
1352
        }
6961 hendricks2 1353
        else
1354
        {
1355
            fogresult = 0.f;
1356
            fogresult2 = -GL_FOG_MAX; // hide fog behind the camera
1357
        }
6515 hendricks2 1358
 
6656 pogokeen 1359
        glFogf(GL_FOG_START, fogresult);
1360
        glFogf(GL_FOG_END, fogresult2);
1361
        glFogfv(GL_FOG_COLOR, (GLfloat *)&fogcol);
6515 hendricks2 1362
 
1363
        return;
1364
    }
1365
 
4393 helixhorne 1366
    // NOTE: for r_usenewshading >= 2, the fog beginning/ending distance results are
3959 helixhorne 1367
    // unused.
7424 terminx 1368
    fogcalc(shade, vis, pal);
6656 pogokeen 1369
    glFogfv(GL_FOG_COLOR, (GLfloat *)&fogcol);
3303 helixhorne 1370
 
4393 helixhorne 1371
    if (r_usenewshading < 2)
6656 pogokeen 1372
        glFogf(GL_FOG_DENSITY, fogresult*factor);
4904 terminx 1373
    else
3303 helixhorne 1374
    {
6656 pogokeen 1375
        glFogf(GL_FOG_START, (GLfloat) FULLVIS_BEGIN);
1376
        glFogf(GL_FOG_END, (GLfloat) FULLVIS_END);
3763 terminx 1377
    }
3303 helixhorne 1378
}
1379
////////////////////
1380
 
1357 terminx 1381
 
3401 helixhorne 1382
static float get_projhack_ratio(void)
1383
{
7656 terminx 1384
    if (glprojectionhacks && !r_yshearing)
3401 helixhorne 1385
    {
7329 terminx 1386
        float const projhack_zoom = 1.4f *
1387
        // adjust for the FOV, increasing the FOV reduces the zenith glitch
1388
        // don't apply if the zenith is cut from the viewing area
1389
        (65536.f / fviewingrange) *
1390
        (float)(windowxy2.y-windowxy1.y+1) /
1391
        (float)(windowxy2.x-windowxy1.x+1) *
1392
        (float)(xdim)/(float)(ydim);
1393
        if (projhack_zoom < 1.f)
1394
            return 1.f;
6523 hendricks2 1395
        static constexpr float const maxcoshoriz = 0.540971179375801f; // 128/sqrt(128^2+199^2) = cos of an horiz diff of 199
7329 terminx 1396
        float const factor = (projhack_zoom - 1.f) * (1.f / maxcoshoriz);
6523 hendricks2 1397
        return 1.f + (factor * (1.f - Bfabsf(gchang)));
3401 helixhorne 1398
    }
1399
 
1400
    // No projection hacks (legacy or new-aspect)
5241 terminx 1401
    return 1.f;
3401 helixhorne 1402
}
1403
 
3041 helixhorne 1404
static void resizeglcheck(void)
5 Plagman 1405
{
5001 terminx 1406
#ifndef EDUKE32_GLES
109 terminx 1407
    //FUK
5075 terminx 1408
    if (lastglpolygonmode != r_polygonmode)
109 terminx 1409
    {
5075 terminx 1410
        lastglpolygonmode = r_polygonmode;
1411
        switch (r_polygonmode)
109 terminx 1412
        {
1413
        default:
331 terminx 1414
        case 0:
6656 pogokeen 1415
            glPolygonMode(GL_FRONT_AND_BACK,GL_FILL); break;
331 terminx 1416
        case 1:
6656 pogokeen 1417
            glPolygonMode(GL_FRONT_AND_BACK,GL_LINE); break;
331 terminx 1418
        case 2:
6656 pogokeen 1419
            glPolygonMode(GL_FRONT_AND_BACK,GL_POINT); break;
109 terminx 1420
        }
1421
    }
5075 terminx 1422
    if (r_polygonmode) //FUK
109 terminx 1423
    {
6656 pogokeen 1424
        glClearColor(1.0,1.0,1.0,0.0);
1425
        glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
109 terminx 1426
    }
5001 terminx 1427
#else
6656 pogokeen 1428
    glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
5001 terminx 1429
#endif
5 Plagman 1430
 
7656 terminx 1431
    if ((glox1 != windowxy1.x) || (gloy1 != windowxy1.y) || (glox2 != windowxy2.x) || (gloy2 != windowxy2.y) || (gloxyaspect != gxyaspect) || (gloyxscale != gyxscale) || (glohoriz2 != ghoriz2) || (glotang != gtang))
109 terminx 1432
    {
5800 terminx 1433
        const int32_t ourxdimen = (windowxy2.x-windowxy1.x+1);
4658 terminx 1434
        float ratio = get_projhack_ratio();
5241 terminx 1435
        const int32_t fovcorrect = (int32_t)(ourxdimen*ratio - ourxdimen);
6523 hendricks2 1436
 
5075 terminx 1437
        ratio = 1.f/ratio;
1438
 
5800 terminx 1439
        glox1 = (float)windowxy1.x; gloy1 = (float)windowxy1.y;
1440
        glox2 = (float)windowxy2.x; gloy2 = (float)windowxy2.y;
109 terminx 1441
 
6939 pogokeen 1442
        glViewport(windowxy1.x-(fovcorrect/2), ydim-(windowxy2.y+1),
5800 terminx 1443
                    ourxdimen+fovcorrect, windowxy2.y-windowxy1.y+1);
5 Plagman 1444
 
6656 pogokeen 1445
        glMatrixMode(GL_PROJECTION);
5075 terminx 1446
 
1447
        float m[4][4];
4675 terminx 1448
        Bmemset(m,0,sizeof(m));
5075 terminx 1449
 
7754 pogokeen 1450
        float const nearclip = 4.0f / (gxyaspect * gyxscale * 1024.f);
7432 terminx 1451
        float const farclip = 64.f;
5075 terminx 1452
 
7432 terminx 1453
        gloxyaspect = gxyaspect;
1454
        gloyxscale = gyxscale;
7656 terminx 1455
        glohoriz2 = ghoriz2;
1456
        glotang = gtang;
7432 terminx 1457
 
1458
        m[0][0] = 1.f;
1459
        m[1][1] = fxdimen / (fydimen * ratio);
7656 terminx 1460
        m[2][0] = 2.f * ghoriz2 * gstang / fxdimen;
7675 terminx 1461
        m[2][1] = 2.f * ghoriz2 * gctang / fydimen;
7432 terminx 1462
        m[2][2] = (farclip + nearclip) / (farclip - nearclip);
1463
        m[2][3] = 1.f;
1464
        m[3][2] = -(2.f * farclip * nearclip) / (farclip - nearclip);
6656 pogokeen 1465
        glLoadMatrixf(&m[0][0]);
5 Plagman 1466
 
6656 pogokeen 1467
        glMatrixMode(GL_MODELVIEW);
1468
        glLoadIdentity();
5 Plagman 1469
 
6776 pogokeen 1470
        if (!nofog) polymost_setFogEnabled(true);
109 terminx 1471
    }
5 Plagman 1472
}
1473
 
4639 terminx 1474
static void fixtransparency(coltype *dapic, vec2_t dasiz, vec2_t dasiz2, int32_t dameth)
5 Plagman 1475
{
5465 hendricks2 1476
    if (!(dameth & DAMETH_MASKPROPS))
1477
        return;
1478
 
4639 terminx 1479
    vec2_t doxy = { dasiz2.x-1, dasiz2.y-1 };
5 Plagman 1480
 
7434 terminx 1481
    if (dameth & DAMETH_CLAMPED)
1482
        doxy = { min(doxy.x, dasiz.x), min(doxy.y, dasiz.y) };
1483
    else  dasiz = dasiz2; //Make repeating textures duplicate top/left parts
3695 helixhorne 1484
 
5075 terminx 1485
    dasiz.x--; dasiz.y--; //Hacks for optimization inside loop
1486
    int32_t const naxsiz2 = -dasiz2.x;
5 Plagman 1487
 
109 terminx 1488
    //Set transparent pixels to average color of neighboring opaque pixels
1489
    //Doing this makes bilinear filtering look much better for masked textures (I.E. sprites)
5829 terminx 1490
    for (bssize_t y=doxy.y; y>=0; y--)
109 terminx 1491
    {
4639 terminx 1492
        coltype * wpptr = &dapic[y*dasiz2.x+doxy.x];
4485 helixhorne 1493
 
5829 terminx 1494
        for (bssize_t x=doxy.x; x>=0; x--,wpptr--)
109 terminx 1495
        {
1496
            if (wpptr->a) continue;
3111 helixhorne 1497
 
5075 terminx 1498
            int r = 0, g = 0, b = 0, j = 0;
1499
 
3041 helixhorne 1500
            if ((x>     0) && (wpptr[     -1].a)) { r += wpptr[     -1].r; g += wpptr[     -1].g; b += wpptr[     -1].b; j++; }
4639 terminx 1501
            if ((x<dasiz.x) && (wpptr[     +1].a)) { r += wpptr[     +1].r; g += wpptr[     +1].g; b += wpptr[     +1].b; j++; }
3041 helixhorne 1502
            if ((y>     0) && (wpptr[naxsiz2].a)) { r += wpptr[naxsiz2].r; g += wpptr[naxsiz2].g; b += wpptr[naxsiz2].b; j++; }
4639 terminx 1503
            if ((y<dasiz.y) && (wpptr[dasiz2.x].a)) { r += wpptr[dasiz2.x].r; g += wpptr[dasiz2.x].g; b += wpptr[dasiz2.x].b; j++; }
5075 terminx 1504
 
331 terminx 1505
            switch (j)
109 terminx 1506
            {
331 terminx 1507
            case 1:
1508
                wpptr->r =   r            ; wpptr->g =   g            ; wpptr->b =   b            ; break;
1509
            case 2:
1510
                wpptr->r = ((r   +  1)>>1); wpptr->g = ((g   +  1)>>1); wpptr->b = ((b   +  1)>>1); break;
1511
            case 3:
1512
                wpptr->r = ((r*85+128)>>8); wpptr->g = ((g*85+128)>>8); wpptr->b = ((b*85+128)>>8); break;
1513
            case 4:
1514
                wpptr->r = ((r   +  2)>>2); wpptr->g = ((g   +  2)>>2); wpptr->b = ((b   +  2)>>2); break;
109 terminx 1515
            }
1516
        }
1517
    }
5 Plagman 1518
}
1519
 
5642 hendricks2 1520
#if defined EDUKE32_GLES
1521
// sorted first in increasing order of size, then in decreasing order of quality
1522
static int32_t const texfmts_rgb_mask[] = { GL_RGB5_A1, GL_RGBA, 0 };
1523
static int32_t const texfmts_rgb[] = { GL_RGB565, GL_RGB5_A1, GL_RGB, GL_RGBA, 0 };
1524
static int32_t const texfmts_rgba[] = { GL_RGBA4, GL_RGBA, 0 } ;
1525
 
5715 hendricks2 1526
static int32_t texfmt_rgb_mask;
1527
static int32_t texfmt_rgb;
1528
static int32_t texfmt_rgba;
5642 hendricks2 1529
 
5690 hendricks2 1530
#if defined EDUKE32_IOS
1531
static int32_t const comprtexfmts_rgb[] = { GL_ETC1_RGB8_OES, 0 };
1532
static int32_t const comprtexfmts_rgba[] = { 0 };
1533
static int32_t const comprtexfmts_rgb_mask[] = { 0 };
1534
#else
7395 hendricks2 1535
static int32_t const comprtexfmts_rgb[] =
1536
{
1537
#ifdef GL_COMPRESSED_RGB8_ETC2
1538
    GL_COMPRESSED_RGB8_ETC2,
1539
#endif
1540
#ifdef GL_ETC1_RGB8_OES
1541
    GL_ETC1_RGB8_OES,
1542
#endif
1543
 
1544
    };
5690 hendricks2 1545
// TODO: waiting on etcpak support for ETC2 with alpha
1546
static int32_t const comprtexfmts_rgba[] = { /*GL_COMPRESSED_RGBA8_ETC2_EAC,*/ 0 };
1547
static int32_t const comprtexfmts_rgb_mask[] = { /*GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2,*/ 0 };
1548
#endif
1549
 
5715 hendricks2 1550
static int32_t comprtexfmt_rgb_mask;
1551
static int32_t comprtexfmt_rgb;
1552
static int32_t comprtexfmt_rgba;
5690 hendricks2 1553
 
1554
# ifdef __cplusplus
1555
extern "C" {
1556
# endif
1557
extern uint64_t ProcessRGB(uint8_t const *);
1558
extern uint64_t ProcessRGB_ETC2(uint8_t const *);
1559
# ifdef __cplusplus
1560
}
1561
# endif
1562
 
5714 hendricks2 1563
typedef uint64_t (*ETCFunction_t)(uint8_t const *);
1564
 
1565
static ETCFunction_t Polymost_PickETCFunction(int32_t const comprtexfmt)
1566
{
1567
    switch (comprtexfmt)
1568
    {
7395 hendricks2 1569
# ifdef GL_ETC1_RGB8_OES
5714 hendricks2 1570
        case GL_ETC1_RGB8_OES:
1571
            return ProcessRGB;
7395 hendricks2 1572
# endif
5714 hendricks2 1573
 
7395 hendricks2 1574
# ifdef GL_COMPRESSED_RGB8_ETC2
5714 hendricks2 1575
        case GL_COMPRESSED_RGB8_ETC2:
1576
            return ProcessRGB_ETC2;
7395 hendricks2 1577
# endif
5714 hendricks2 1578
 
1579
# if 0
1580
        case GL_COMPRESSED_RGBA8_ETC2_EAC:
7395 hendricks2 1581
            fallthrough__;
5714 hendricks2 1582
        case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
7395 hendricks2 1583
            fallthrough__;
5714 hendricks2 1584
# endif
1585
 
1586
        default:
1587
            EDUKE32_UNREACHABLE_SECTION(return NULL);
1588
    }
1589
}
1590
 
5715 hendricks2 1591
static int Polymost_ConfirmNoGLError(void)
1592
{
1593
    GLenum checkerr, err = GL_NO_ERROR;
6656 pogokeen 1594
    while ((checkerr = glGetError()) != GL_NO_ERROR)
5715 hendricks2 1595
        err = checkerr;
1596
 
1597
    return err == GL_NO_ERROR;
1598
}
1599
 
1600
static int32_t Polymost_TryDummyTexture(coltype const * const pic, int32_t const * formats)
1601
{
1602
    while (*formats)
1603
    {
6656 pogokeen 1604
        glTexImage2D(GL_TEXTURE_2D, 0, *formats, 4,4, 0, GL_RGBA, GL_UNSIGNED_BYTE, pic);
5715 hendricks2 1605
 
1606
        if (Polymost_ConfirmNoGLError())
1607
            return *formats;
1608
 
1609
        ++formats;
1610
    }
1611
 
1612
    initputs("No texture formats supported?!\n");
1613
 
1614
    return 0;
1615
}
1616
 
1617
static int32_t Polymost_TryCompressedDummyTexture(coltype const * const pic, int32_t const * formats)
1618
{
1619
    while (*formats)
1620
    {
1621
        ETCFunction_t func = Polymost_PickETCFunction(*formats);
1622
        uint64_t const comprpic = func((uint8_t const *)pic);
1623
        jwzgles_glCompressedTexImage2D(GL_TEXTURE_2D, 0, *formats, 4,4, 0, sizeof(uint64_t), &comprpic);
1624
 
1625
        if (Polymost_ConfirmNoGLError())
1626
            return *formats;
1627
 
1628
        ++formats;
1629
    }
1630
 
1631
    return 0;
1632
}
1633
 
1634
static void Polymost_DetermineTextureFormatSupport(void)
1635
{
1636
    // init dummy texture to trigger possible failure of all compression modes
1637
    coltype pic[4*4] = { { 0, 0, 0, 0 } };
1638
    GLuint tex = 0;
1639
 
6656 pogokeen 1640
    glGenTextures(1, &tex);
1641
    glBindTexture(GL_TEXTURE_2D, tex);
5715 hendricks2 1642
 
1643
    BuildGLErrorCheck(); // XXX: Clear errors.
1644
 
1645
    texfmt_rgb = Polymost_TryDummyTexture(pic, texfmts_rgb);
1646
    texfmt_rgba = Polymost_TryDummyTexture(pic, texfmts_rgba);
1647
    texfmt_rgb_mask = Polymost_TryDummyTexture(pic, texfmts_rgb_mask);
1648
 
1649
    comprtexfmt_rgb = Polymost_TryCompressedDummyTexture(pic, comprtexfmts_rgb);
1650
    comprtexfmt_rgba = Polymost_TryCompressedDummyTexture(pic, comprtexfmts_rgba);
1651
    comprtexfmt_rgb_mask = Polymost_TryCompressedDummyTexture(pic, comprtexfmts_rgb_mask);
1652
 
6656 pogokeen 1653
    glDeleteTextures(1, &tex);
5715 hendricks2 1654
}
5642 hendricks2 1655
#endif
1656
 
5690 hendricks2 1657
static void Polymost_SendTexToDriver(int32_t const doalloc,
1658
                                     vec2_t const siz,
1659
                                     int32_t const texfmt,
1660
                                     coltype const * const pic,
1661
                                     int32_t const intexfmt,
5715 hendricks2 1662
#if defined EDUKE32_GLES
1663
                                     int32_t const comprtexfmt,
5690 hendricks2 1664
                                     int32_t const texcompress_ok,
1665
#endif
1666
                                     int32_t const level)
1667
{
1668
#if defined EDUKE32_GLES
5715 hendricks2 1669
    if (texcompress_ok && comprtexfmt && (siz.x & 3) == 0 && (siz.y & 3) == 0)
5690 hendricks2 1670
    {
1671
        size_t const picLength = siz.x * siz.y;
1672
        size_t const fourRows = siz.x << 2u;
1673
        GLsizei const imageSize = picLength >> 1u; // 4x4 pixels --> 8 bytes
1674
        uint8_t * const comprpic = (uint8_t *)Xaligned_alloc(8, imageSize);
1675
 
5715 hendricks2 1676
        ETCFunction_t func = Polymost_PickETCFunction(comprtexfmt);
5690 hendricks2 1677
 
5715 hendricks2 1678
        coltype buf[4*4];
1679
        uint64_t * out = (uint64_t *)comprpic;
1680
        for (coltype const * row = pic, * const pic_end = pic + picLength; row < pic_end; row += fourRows)
1681
            for (coltype const * block = row, * const row_end = row + siz.x; block < row_end; block += 4)
1682
            {
1683
                buf[0] = block[0];
1684
                buf[1] = block[siz.x];
1685
                buf[2] = block[siz.x*2];
1686
                buf[3] = block[siz.x*3];
1687
                buf[4] = block[1];
1688
                buf[5] = block[siz.x+1];
1689
                buf[6] = block[siz.x*2+1];
1690
                buf[7] = block[siz.x*3+1];
1691
                buf[8] = block[2];
1692
                buf[9] = block[siz.x+2];
1693
                buf[10] = block[siz.x*2+2];
1694
                buf[11] = block[siz.x*3+2];
1695
                buf[12] = block[3];
1696
                buf[13] = block[siz.x+3];
1697
                buf[14] = block[siz.x*2+3];
1698
                buf[15] = block[siz.x*3+3];
5690 hendricks2 1699
 
5715 hendricks2 1700
                *out++ = func((uint8_t const *)buf);
1701
            }
5690 hendricks2 1702
 
5715 hendricks2 1703
        if (doalloc & 1)
1704
            jwzgles_glCompressedTexImage2D(GL_TEXTURE_2D, level, comprtexfmt, siz.x,siz.y, 0, imageSize, comprpic);
1705
        else
1706
            jwzgles_glCompressedTexSubImage2D(GL_TEXTURE_2D, level, 0,0, siz.x,siz.y, comprtexfmt, imageSize, comprpic);
5690 hendricks2 1707
 
7705 terminx 1708
        Xaligned_free(comprpic);
5690 hendricks2 1709
 
5715 hendricks2 1710
        return;
5690 hendricks2 1711
    }
1712
#endif
1713
 
6653 pogokeen 1714
#if B_BIG_ENDIAN
1715
    GLenum type = GL_UNSIGNED_INT_8_8_8_8;
1716
#else
1717
    GLenum type = GL_UNSIGNED_INT_8_8_8_8_REV;
1718
#endif
5715 hendricks2 1719
    if (doalloc & 1)
6656 pogokeen 1720
        glTexImage2D(GL_TEXTURE_2D, level, intexfmt, siz.x,siz.y, 0, texfmt, type, pic);
5715 hendricks2 1721
    else
6656 pogokeen 1722
        glTexSubImage2D(GL_TEXTURE_2D, level, 0,0, siz.x,siz.y, texfmt, type, pic);
5690 hendricks2 1723
}
1724
 
5642 hendricks2 1725
void uploadtexture(int32_t doalloc, vec2_t siz, int32_t texfmt,
5075 terminx 1726
                   coltype *pic, vec2_t tsiz, int32_t dameth)
5 Plagman 1727
{
5647 hendricks2 1728
    const int artimmunity = !!(dameth & DAMETH_ARTIMMUNITY);
5075 terminx 1729
    const int hi = !!(dameth & DAMETH_HI);
5647 hendricks2 1730
    const int nodownsize = !!(dameth & DAMETH_NODOWNSIZE) || artimmunity;
5075 terminx 1731
    const int nomiptransfix  = !!(dameth & DAMETH_NOFIX);
5690 hendricks2 1732
    const int texcompress_ok = !(dameth & DAMETH_NOTEXCOMPRESS) && (glusetexcompr == 2 || (glusetexcompr && !artimmunity));
5 Plagman 1733
 
5642 hendricks2 1734
#if !defined EDUKE32_GLES
1735
    int32_t intexfmt;
5690 hendricks2 1736
    if (texcompress_ok && glinfo.texcompr)
6656 pogokeen 1737
        intexfmt = GL_COMPRESSED_RGBA;
5642 hendricks2 1738
    else
6653 pogokeen 1739
        intexfmt = GL_RGBA8;
5642 hendricks2 1740
#else
7395 hendricks2 1741
    const int hasalpha  = !!(dameth & (DAMETH_HASALPHA|DAMETH_ONEBITALPHA));
5642 hendricks2 1742
    const int onebitalpha  = !!(dameth & DAMETH_ONEBITALPHA);
1743
 
5715 hendricks2 1744
    int32_t const intexfmt = hasalpha ? (onebitalpha ? texfmt_rgb_mask : texfmt_rgba) : texfmt_rgb;
1745
    int32_t const comprtexfmt = hasalpha ? (onebitalpha ? comprtexfmt_rgb_mask : comprtexfmt_rgba) : comprtexfmt_rgb;
5642 hendricks2 1746
#endif
1747
 
5647 hendricks2 1748
    dameth &= ~DAMETH_UPLOADTEXTURE_MASK;
5645 hendricks2 1749
 
584 terminx 1750
    if (gltexmaxsize <= 0)
1751
    {
109 terminx 1752
        GLint i = 0;
6656 pogokeen 1753
        glGetIntegerv(GL_MAX_TEXTURE_SIZE, &i);
109 terminx 1754
        if (!i) gltexmaxsize = 6;   // 2^6 = 64 == default GL max texture size
584 terminx 1755
        else
1756
        {
109 terminx 1757
            gltexmaxsize = 0;
1758
            for (; i>1; i>>=1) gltexmaxsize++;
5652 terminx 1759
#ifdef EDUKE32_GLES
5711 hendricks2 1760
            while ((1<<(gltexmaxsize-1)) > xdim)
5652 terminx 1761
                gltexmaxsize--;
1762
#endif
109 terminx 1763
        }
1764
    }
5 Plagman 1765
 
5075 terminx 1766
    gltexmiplevel = max(0, min(gltexmaxsize-1, gltexmiplevel));
5 Plagman 1767
 
5075 terminx 1768
    int miplevel = gltexmiplevel;
916 terminx 1769
 
5075 terminx 1770
    while ((siz.x >> miplevel) > (1 << gltexmaxsize) || (siz.y >> miplevel) > (1 << gltexmaxsize))
1771
        miplevel++;
109 terminx 1772
 
5640 hendricks2 1773
    if (hi && !nodownsize && r_downsize > miplevel)
5075 terminx 1774
        miplevel = r_downsize;
1775
 
6654 pogokeen 1776
    // don't use mipmaps if mipmapping is disabled
6700 hendricks2 1777
    //POGO: until the texcacheheader can be updated, generate the mipmaps texcache expects if it's enabled
6675 pogokeen 1778
    if (!glusetexcache &&
1779
        (glfiltermodes[gltexfiltermode].min == GL_NEAREST ||
1780
         glfiltermodes[gltexfiltermode].min == GL_LINEAR))
6654 pogokeen 1781
    {
6656 pogokeen 1782
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
1783
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
6654 pogokeen 1784
    }
6700 hendricks2 1785
 
5075 terminx 1786
    if (!miplevel)
5690 hendricks2 1787
        Polymost_SendTexToDriver(doalloc, siz, texfmt, pic,
1788
                                 intexfmt,
5715 hendricks2 1789
#if defined EDUKE32_GLES
1790
                                 comprtexfmt,
5690 hendricks2 1791
                                 texcompress_ok,
1792
#endif
1793
                                 0);
6700 hendricks2 1794
 
6654 pogokeen 1795
    // don't generate mipmaps if we're not going to use them
6675 pogokeen 1796
    if (!glusetexcache &&
1797
        (glfiltermodes[gltexfiltermode].min == GL_NEAREST ||
1798
         glfiltermodes[gltexfiltermode].min == GL_LINEAR))
6654 pogokeen 1799
    {
1800
        return;
1801
    }
109 terminx 1802
 
5075 terminx 1803
    vec2_t siz2 = siz;
1804
 
5829 terminx 1805
    for (bssize_t j=1; (siz2.x > 1) || (siz2.y > 1); j++)
109 terminx 1806
    {
5075 terminx 1807
        vec2_t const siz3 = { max(1, siz2.x >> 1), max(1, siz2.y >> 1) };  // this came from the GL_ARB_texture_non_power_of_two spec
109 terminx 1808
        //x3 = ((x2+1)>>1); y3 = ((y2+1)>>1);
4485 helixhorne 1809
 
5829 terminx 1810
        for (bssize_t y=0; y<siz3.y; y++)
109 terminx 1811
        {
5075 terminx 1812
            coltype *wpptr = &pic[y*siz3.x];
1813
            coltype const *rpptr = &pic[(y<<1)*siz2.x];
4485 helixhorne 1814
 
5829 terminx 1815
            for (bssize_t x=0; x<siz3.x; x++,wpptr++,rpptr+=2)
109 terminx 1816
            {
4485 helixhorne 1817
                int32_t r=0, g=0, b=0, a=0, k=0;
1818
 
3041 helixhorne 1819
                if (rpptr[0].a)                  { r += rpptr[0].r; g += rpptr[0].g; b += rpptr[0].b; a += rpptr[0].a; k++; }
5075 terminx 1820
                if ((x+x+1 < siz2.x) && (rpptr[1].a)) { r += rpptr[1].r; g += rpptr[1].g; b += rpptr[1].b; a += rpptr[1].a; k++; }
1821
                if (y+y+1 < siz2.y)
109 terminx 1822
                {
5075 terminx 1823
                    if ((rpptr[siz2.x].a)) { r += rpptr[siz2.x  ].r; g += rpptr[siz2.x  ].g; b += rpptr[siz2.x  ].b; a += rpptr[siz2.x  ].a; k++; }
1824
                    if ((x+x+1 < siz2.x) && (rpptr[siz2.x+1].a)) { r += rpptr[siz2.x+1].r; g += rpptr[siz2.x+1].g; b += rpptr[siz2.x+1].b; a += rpptr[siz2.x+1].a; k++; }
109 terminx 1825
                }
331 terminx 1826
                switch (k)
109 terminx 1827
                {
1828
                case 0:
331 terminx 1829
                case 1:
1830
                    wpptr->r = r; wpptr->g = g; wpptr->b = b; wpptr->a = a; break;
1831
                case 2:
1832
                    wpptr->r = ((r+1)>>1); wpptr->g = ((g+1)>>1); wpptr->b = ((b+1)>>1); wpptr->a = ((a+1)>>1); break;
1833
                case 3:
1834
                    wpptr->r = ((r*85+128)>>8); wpptr->g = ((g*85+128)>>8); wpptr->b = ((b*85+128)>>8); wpptr->a = ((a*85+128)>>8); break;
1835
                case 4:
1836
                    wpptr->r = ((r+2)>>2); wpptr->g = ((g+2)>>2); wpptr->b = ((b+2)>>2); wpptr->a = ((a+2)>>2); break;
1837
                default:
4680 terminx 1838
                    EDUKE32_UNREACHABLE_SECTION(break);
109 terminx 1839
                }
1840
                //if (wpptr->a) wpptr->a = 255;
1841
            }
1842
        }
4639 terminx 1843
 
5075 terminx 1844
        if (!nomiptransfix)
4639 terminx 1845
        {
5075 terminx 1846
            vec2_t const tsizzle = { (tsiz.x + (1 << j)-1) >> j, (tsiz.y + (1 << j)-1) >> j };
4639 terminx 1847
 
6263 hendricks2 1848
            fixtransparency(pic, tsizzle, siz3, dameth);
4639 terminx 1849
        }
1850
 
5075 terminx 1851
        if (j >= miplevel)
5690 hendricks2 1852
            Polymost_SendTexToDriver(doalloc, siz3, texfmt, pic,
1853
                                     intexfmt,
5715 hendricks2 1854
#if defined EDUKE32_GLES
1855
                                     comprtexfmt,
5690 hendricks2 1856
                                     texcompress_ok,
1857
#endif
1858
                                     j - miplevel);
5075 terminx 1859
 
1860
        siz2 = siz3;
109 terminx 1861
    }
5 Plagman 1862
}
1863
 
6883 pogokeen 1864
void uploadtextureindexed(int32_t doalloc, vec2_t offset, vec2_t siz, intptr_t tile)
6776 pogokeen 1865
{
6883 pogokeen 1866
    if (doalloc & 1)
1867
    {
1868
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
1869
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
1870
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1871
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1872
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1);
2141 helixhorne 1873
 
6776 pogokeen 1874
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, siz.y, siz.x, 0, GL_RED, GL_UNSIGNED_BYTE, (void*) tile);
6883 pogokeen 1875
    }
6776 pogokeen 1876
    else
6883 pogokeen 1877
    {
1878
        glTexSubImage2D(GL_TEXTURE_2D, 0, offset.x, offset.y, siz.y, siz.x, GL_RED, GL_UNSIGNED_BYTE, (void*) tile);
1879
    }
6776 pogokeen 1880
}
1881
 
1882
void uploadbasepalette(int32_t basepalnum)
1883
{
1884
    if (!polymost1BasicShaderProgramID)
1885
    {
1886
        //POGO: if we haven't initialized properly yet, we shouldn't be uploading base palettes
1887
        return;
1888
    }
1889
    if (!basepaltable[basepalnum])
1890
    {
1891
        return;
1892
    }
1893
 
6936 pogokeen 1894
    //POGO: this is only necessary for GL fog/vertex color shade compatibility, since those features don't index into shade tables
6776 pogokeen 1895
    uint8_t basepalWFullBrightInfo[4*256];
1896
    for (int i = 0; i < 256; ++i)
1897
    {
1898
        basepalWFullBrightInfo[i*4] = basepaltable[basepalnum][i*3];
1899
        basepalWFullBrightInfo[i*4+1] = basepaltable[basepalnum][i*3+1];
1900
        basepalWFullBrightInfo[i*4+2] = basepaltable[basepalnum][i*3+2];
1901
        basepalWFullBrightInfo[i*4+3] = 0-(IsPaletteIndexFullbright(i) != 0);
1902
    }
1903
 
1904
    char allocateTexture = !paletteTextureIDs[basepalnum];
1905
    if (allocateTexture)
1906
    {
1907
        glGenTextures(1, &paletteTextureIDs[basepalnum]);
1908
    }
1909
    glBindTexture(GL_TEXTURE_2D, paletteTextureIDs[basepalnum]);
1910
    if (allocateTexture)
1911
    {
6777 pogokeen 1912
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
1913
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
1914
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1915
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6883 pogokeen 1916
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1);
6777 pogokeen 1917
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1918
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
6776 pogokeen 1919
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 256, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, basepalWFullBrightInfo);
1920
    }
1921
    else
1922
    {
1923
        glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 256, 1, GL_RGBA, GL_UNSIGNED_BYTE, basepalWFullBrightInfo);
1924
    }
1925
}
1926
 
1927
void uploadpalswap(int32_t palookupnum)
1928
{
1929
    if (!polymost1BasicShaderProgramID)
1930
    {
1931
        //POGO: if we haven't initialized properly yet, we shouldn't be uploading palette swap tables
1932
        return;
1933
    }
1934
    if (!palookup[palookupnum])
1935
    {
1936
        return;
1937
    }
1938
 
6777 pogokeen 1939
    char allocateTexture = !palswapTextureID;
6776 pogokeen 1940
    if (allocateTexture)
1941
    {
6777 pogokeen 1942
        glGenTextures(1, &palswapTextureID);
6776 pogokeen 1943
    }
6777 pogokeen 1944
    glBindTexture(GL_TEXTURE_2D, palswapTextureID);
6776 pogokeen 1945
    if (allocateTexture)
1946
    {
6777 pogokeen 1947
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
1948
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
1949
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1950
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6883 pogokeen 1951
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1);
6777 pogokeen 1952
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1953
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1954
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, PALSWAP_TEXTURE_SIZE, PALSWAP_TEXTURE_SIZE, 0, GL_RED, GL_UNSIGNED_BYTE, NULL);
6776 pogokeen 1955
    }
6777 pogokeen 1956
 
1957
    int32_t column = palookupnum%(PALSWAP_TEXTURE_SIZE/256);
1958
    int32_t row = palookupnum/(PALSWAP_TEXTURE_SIZE/256);
1959
    int32_t rowOffset = (numshades+1)*row;
1960
    if (rowOffset > PALSWAP_TEXTURE_SIZE)
6776 pogokeen 1961
    {
6777 pogokeen 1962
        OSD_Printf("Polymost: palswaps are too large for palswap tilesheet!\n");
1963
        return;
6776 pogokeen 1964
    }
6777 pogokeen 1965
    glTexSubImage2D(GL_TEXTURE_2D, 0, 256*column, rowOffset, 256, numshades+1, GL_RED, GL_UNSIGNED_BYTE, palookup[palookupnum]);
6776 pogokeen 1966
}
1967
 
1968
 
2142 helixhorne 1969
#if 0
2141 helixhorne 1970
// TODO: make configurable
1971
static int32_t tile_is_sky(int32_t tilenum)
1972
{
2142 helixhorne 1973
    return return (tilenum >= 78 /*CLOUDYOCEAN*/ && tilenum <= 99 /*REDSKY2*/);
2141 helixhorne 1974
}
5961 hendricks2 1975
# define clamp_if_tile_is_sky(x, y) (tile_is_sky(x) ? (y) : GL_REPEAT)
2142 helixhorne 1976
#else
5961 hendricks2 1977
# define clamp_if_tile_is_sky(x, y) (GL_REPEAT)
2142 helixhorne 1978
#endif
2141 helixhorne 1979
 
5075 terminx 1980
static void polymost_setuptexture(const int32_t dameth, int filter)
3041 helixhorne 1981
{
4623 terminx 1982
    const GLuint clamp_mode = glinfo.clamptoedge ? GL_CLAMP_TO_EDGE : GL_CLAMP;
1983
 
5079 terminx 1984
    gltexfiltermode = clamp(gltexfiltermode, 0, NUMGLFILTERMODES-1);
1985
 
5001 terminx 1986
    if (filter == -1)
1987
        filter = gltexfiltermode;
3041 helixhorne 1988
 
6656 pogokeen 1989
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, glfiltermodes[filter].mag);
1990
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, glfiltermodes[filter].min);
5001 terminx 1991
 
5526 hendricks2 1992
#ifdef USE_GLEXT
4605 terminx 1993
    if (glinfo.maxanisotropy > 1.f)
3041 helixhorne 1994
    {
5001 terminx 1995
        uint32_t i = (unsigned)Blrintf(glinfo.maxanisotropy);
4623 terminx 1996
 
1997
        if ((unsigned)glanisotropy > i)
1998
            glanisotropy = i;
1999
 
6656 pogokeen 2000
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, glanisotropy);
3041 helixhorne 2001
    }
5001 terminx 2002
#endif
3041 helixhorne 2003
 
4486 helixhorne 2004
    if (!(dameth & DAMETH_CLAMPED))
3041 helixhorne 2005
    {
6656 pogokeen 2006
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, clamp_if_tile_is_sky(dapic, clamp_mode));
2007
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
3041 helixhorne 2008
    }
2009
    else
2010
    {
5001 terminx 2011
        // For sprite textures, clamping looks better than wrapping
6656 pogokeen 2012
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, clamp_mode);
2013
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, clamp_mode);
3041 helixhorne 2014
    }
2015
}
2016
 
6776 pogokeen 2017
static void gloadtile_art_indexed(int32_t dapic, int32_t dameth, pthtyp *pth, int32_t doalloc)
2018
{
7694 terminx 2019
    vec2_16_t const & tsizart = tilesiz[dapic];
6776 pogokeen 2020
    vec2_t siz = { tsizart.x, tsizart.y };
2021
    //POGOTODO: npoty
2022
    char npoty = 0;
2023
 
2024
    //POGOTODO: if !glinfo.texnpot, then we could allocate a texture of the pow2 size, and then populate the subportion using buffersubdata func
2025
    //if (!glinfo.texnpot)
2026
 
6883 pogokeen 2027
    Tile tile = {};
6776 pogokeen 2028
    if (waloff[dapic])
2029
    {
6883 pogokeen 2030
        char tileIsPacked = tilepacker_getTile(dapic+1, &tile);
2031
        if (tileIsPacked &&
2032
            tile.rect.width == (uint32_t) tsizart.y &&
2033
            tile.rect.height == (uint32_t) tsizart.x)
6776 pogokeen 2034
        {
6883 pogokeen 2035
            pth->glpic = tilesheetTexIDs[tile.tilesheetID];
2036
            doalloc = false;
2037
        }
2038
        else if (doalloc)
2039
        {
6776 pogokeen 2040
            glGenTextures(1, (GLuint *)&pth->glpic);
2041
        }
6883 pogokeen 2042
        glBindTexture(GL_TEXTURE_2D, pth->glpic);
6776 pogokeen 2043
 
6883 pogokeen 2044
        if (doalloc)
2045
        {
2046
            const GLuint clamp_mode = glinfo.clamptoedge ? GL_CLAMP_TO_EDGE : GL_CLAMP;
2047
            if (!(dameth & DAMETH_CLAMPED))
2048
            {
2049
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, clamp_if_tile_is_sky(dapic, clamp_mode));
2050
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
2051
            }
2052
            else
2053
            {
2054
                // For sprite textures, clamping looks better than wrapping
2055
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, clamp_mode);
2056
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, clamp_mode);
2057
            }
2058
        }
2059
        uploadtextureindexed(doalloc, {(int32_t) tile.rect.u, (int32_t) tile.rect.v}, siz, waloff[dapic]);
6776 pogokeen 2060
    }
2061
    else
2062
    {
6883 pogokeen 2063
        tilepacker_getTile(0, &tile);
2064
        pth->glpic = tilesheetTexIDs[tile.tilesheetID];
6776 pogokeen 2065
    }
2066
 
2067
    pth->picnum = dapic;
2068
    pth->palnum = 0;
2069
    pth->shade = 0;
2070
    pth->effects = 0;
7612 pogokeen 2071
    pth->flags = TO_PTH_CLAMPED(dameth) | TO_PTH_NOTRANSFIX(dameth) | (PTH_HASALPHA|PTH_ONEBITALPHA) | (npoty*PTH_NPOTWALL) | PTH_INDEXED;
6776 pogokeen 2072
    pth->hicr = NULL;
2073
}
2074
 
5145 hendricks2 2075
void gloadtile_art(int32_t dapic, int32_t dapal, int32_t tintpalnum, int32_t dashade, int32_t dameth, pthtyp *pth, int32_t doalloc)
5 Plagman 2076
{
6776 pogokeen 2077
    if (dameth & PTH_INDEXED)
2078
    {
2079
        return gloadtile_art_indexed(dapic, dameth, pth, doalloc);
2080
    }
2081
 
3146 helixhorne 2082
    static int32_t fullbrightloadingpass = 0;
7694 terminx 2083
    vec2_16_t const & tsizart = tilesiz[dapic];
6263 hendricks2 2084
    vec2_t siz = { 0, 0 }, tsiz = { tsizart.x, tsizart.y };
7078 terminx 2085
    int const picdim = tsiz.x*tsiz.y;
5712 hendricks2 2086
    char hasalpha = 0, hasfullbright = 0;
5713 hendricks2 2087
    char npoty = 0;
3146 helixhorne 2088
 
5713 hendricks2 2089
    texcacheheader cachead;
2090
    char texcacheid[BMAX_PATH];
584 terminx 2091
    {
5713 hendricks2 2092
        // Absolutely disgusting.
2093
        uint32_t firstint = 0;
2094
        if (waloff[dapic])
2095
            Bmemcpy(&firstint, (void *)waloff[dapic], min(4, picdim));
2096
        sprintf(texcacheid, "%08x", firstint);
2097
    }
2098
    texcache_calcid(texcacheid, texcacheid, picdim | ((unsigned)dapal<<24u), DAMETH_NARROW_MASKPROPS(dameth) | ((unsigned)dapic<<8u) | ((unsigned)dashade<<24u), tintpalnum);
2099
    int32_t gotcache = texcache_readtexheader(texcacheid, &cachead, 0);
2100
 
2101
    if (gotcache && !texcache_loadtile(&cachead, &doalloc, pth))
2102
    {
2103
        hasalpha = !!(cachead.flags & CACHEAD_HASALPHA);
2104
        hasfullbright = !!(cachead.flags & CACHEAD_HASFULLBRIGHT);
2105
        npoty = !!(cachead.flags & CACHEAD_NPOTWALL);
2106
    }
2107
    else
2108
    {
5712 hendricks2 2109
        if (!glinfo.texnpot)
2110
        {
2111
            for (siz.x = 1; siz.x < tsiz.x; siz.x += siz.x) { }
2112
            for (siz.y = 1; siz.y < tsiz.y; siz.y += siz.y) { }
2113
        }
584 terminx 2114
        else
5712 hendricks2 2115
        {
2116
            if ((tsiz.x|tsiz.y) == 0)
2117
                siz.x = siz.y = 1;
2118
            else
2119
                siz = tsiz;
2120
        }
5 Plagman 2121
 
5712 hendricks2 2122
        coltype *pic = (coltype *)Xmalloc(siz.x*siz.y*sizeof(coltype));
5 Plagman 2123
 
5712 hendricks2 2124
        if (!waloff[dapic])
109 terminx 2125
        {
5712 hendricks2 2126
            //Force invalid textures to draw something - an almost purely transparency texture
2127
            //This allows the Z-buffer to be updated for mirrors (which are invalidated textures)
2128
            pic[0].r = pic[0].g = pic[0].b = 0; pic[0].a = 1;
2129
            tsiz.x = tsiz.y = 1; hasalpha = 1;
2130
        }
2131
        else
2132
        {
2133
            const int dofullbright = !(picanm[dapic].sf & PICANM_NOFULLBRIGHT_BIT) && !(globalflags & GLOBAL_NO_GL_FULLBRIGHT);
3146 helixhorne 2134
 
5829 terminx 2135
            for (bssize_t y = 0; y < siz.y; y++)
109 terminx 2136
            {
5712 hendricks2 2137
                coltype *wpptr = &pic[y * siz.x];
2138
                int32_t y2 = (y < tsiz.y) ? y : y - tsiz.y;
3146 helixhorne 2139
 
5829 terminx 2140
                for (bssize_t x = 0; x < siz.x; x++, wpptr++)
4485 helixhorne 2141
                {
5712 hendricks2 2142
                    int32_t dacol;
2143
                    int32_t x2 = (x < tsiz.x) ? x : x-tsiz.x;
3146 helixhorne 2144
 
5712 hendricks2 2145
                    if ((dameth & DAMETH_CLAMPED) && (x >= tsiz.x || y >= tsiz.y)) //Clamp texture
2146
                    {
2147
                        wpptr->r = wpptr->g = wpptr->b = wpptr->a = 0;
2148
                        continue;
2149
                    }
3146 helixhorne 2150
 
5712 hendricks2 2151
                    dacol = *(char *)(waloff[dapic]+x2*tsiz.y+y2);
5467 hendricks2 2152
 
5712 hendricks2 2153
                    if (dacol == 255)
584 terminx 2154
                    {
3146 helixhorne 2155
                        wpptr->a = 0;
2156
                        hasalpha = 1;
584 terminx 2157
                    }
5712 hendricks2 2158
                    else
2159
                        wpptr->a = 255;
3146 helixhorne 2160
 
6440 terminx 2161
                    char *p = (char *)(palookup[dapal])+(int32_t)(dashade<<8);
2162
                    dacol = (uint8_t)p[dacol];
5145 hendricks2 2163
 
5712 hendricks2 2164
                    if (!fullbrightloadingpass)
5145 hendricks2 2165
                    {
5712 hendricks2 2166
                        // regular texture
2167
                        if (IsPaletteIndexFullbright(dacol) && dofullbright)
2168
                            hasfullbright = 1;
5145 hendricks2 2169
                    }
5712 hendricks2 2170
                    else
5145 hendricks2 2171
                    {
5712 hendricks2 2172
                        // texture with only fullbright areas
2173
                        if (!IsPaletteIndexFullbright(dacol))    // regular colors
2174
                        {
2175
                            wpptr->a = 0;
2176
                            hasalpha = 1;
2177
                        }
5145 hendricks2 2178
                    }
5146 hendricks2 2179
 
5712 hendricks2 2180
                    bricolor((palette_t *)wpptr, dacol);
2181
 
2182
                    if (!fullbrightloadingpass && tintpalnum >= 0)
5146 hendricks2 2183
                    {
6215 hendricks2 2184
                        polytint_t const & tint = hictinting[tintpalnum];
2185
                        polytintflags_t const effect = tint.f;
2186
                        uint8_t const r = tint.r;
2187
                        uint8_t const g = tint.g;
2188
                        uint8_t const b = tint.b;
5712 hendricks2 2189
 
2190
                        if (effect & HICTINT_GRAYSCALE)
2191
                        {
2192
                            wpptr->g = wpptr->r = wpptr->b = (uint8_t) ((wpptr->r * GRAYSCALE_COEFF_RED) +
2193
                                                                  (wpptr->g * GRAYSCALE_COEFF_GREEN) +
2194
                                                                  (wpptr->b * GRAYSCALE_COEFF_BLUE));
2195
                        }
2196
 
2197
                        if (effect & HICTINT_INVERT)
2198
                        {
2199
                            wpptr->b = 255 - wpptr->b;
2200
                            wpptr->g = 255 - wpptr->g;
2201
                            wpptr->r = 255 - wpptr->r;
2202
                        }
2203
 
2204
                        if (effect & HICTINT_COLORIZE)
2205
                        {
2206
                            wpptr->b = min((int32_t)((wpptr->b) * b) >> 6, 255);
2207
                            wpptr->g = min((int32_t)((wpptr->g) * g) >> 6, 255);
2208
                            wpptr->r = min((int32_t)((wpptr->r) * r) >> 6, 255);
2209
                        }
2210
 
2211
                        switch (effect & HICTINT_BLENDMASK)
2212
                        {
2213
                            case HICTINT_BLEND_SCREEN:
2214
                                wpptr->b = 255 - (((255 - wpptr->b) * (255 - b)) >> 8);
2215
                                wpptr->g = 255 - (((255 - wpptr->g) * (255 - g)) >> 8);
2216
                                wpptr->r = 255 - (((255 - wpptr->r) * (255 - r)) >> 8);
2217
                                break;
2218
                            case HICTINT_BLEND_OVERLAY:
2219
                                wpptr->b = wpptr->b < 128 ? (wpptr->b * b) >> 7 : 255 - (((255 - wpptr->b) * (255 - b)) >> 7);
2220
                                wpptr->g = wpptr->g < 128 ? (wpptr->g * g) >> 7 : 255 - (((255 - wpptr->g) * (255 - g)) >> 7);
2221
                                wpptr->r = wpptr->r < 128 ? (wpptr->r * r) >> 7 : 255 - (((255 - wpptr->r) * (255 - r)) >> 7);
2222
                                break;
2223
                            case HICTINT_BLEND_HARDLIGHT:
2224
                                wpptr->b = b < 128 ? (wpptr->b * b) >> 7 : 255 - (((255 - wpptr->b) * (255 - b)) >> 7);
2225
                                wpptr->g = g < 128 ? (wpptr->g * g) >> 7 : 255 - (((255 - wpptr->g) * (255 - g)) >> 7);
2226
                                wpptr->r = r < 128 ? (wpptr->r * r) >> 7 : 255 - (((255 - wpptr->r) * (255 - r)) >> 7);
2227
                                break;
2228
                        }
5146 hendricks2 2229
                    }
6700 hendricks2 2230
 
6653 pogokeen 2231
                    //swap r & b so that we deal with the data as BGRA
2232
                    uint8_t tmpR = wpptr->r;
2233
                    wpptr->r = wpptr->b;
2234
                    wpptr->b = tmpR;
5145 hendricks2 2235
                }
109 terminx 2236
            }
2237
        }
5 Plagman 2238
 
6656 pogokeen 2239
        if (doalloc) glGenTextures(1,(GLuint *)&pth->glpic); //# of textures (make OpenGL allocate structure)
6883 pogokeen 2240
        glBindTexture(GL_TEXTURE_2D, pth->glpic);
5 Plagman 2241
 
5712 hendricks2 2242
        fixtransparency(pic,tsiz,siz,dameth);
4498 helixhorne 2243
 
5712 hendricks2 2244
        if (polymost_want_npotytex(dameth, siz.y) && tsiz.x == siz.x && tsiz.y == siz.y)  // XXX
2245
        {
2246
            const int32_t nextpoty = 1 << ((picsiz[dapic] >> 4) + 1);
2247
            const int32_t ydif = nextpoty - siz.y;
2248
            coltype *paddedpic;
5001 terminx 2249
 
5712 hendricks2 2250
            Bassert(ydif < siz.y);
4498 helixhorne 2251
 
5712 hendricks2 2252
            paddedpic = (coltype *)Xrealloc(pic, siz.x * nextpoty * sizeof(coltype));
4498 helixhorne 2253
 
5712 hendricks2 2254
            pic = paddedpic;
2255
            Bmemcpy(&pic[siz.x * siz.y], pic, siz.x * ydif * sizeof(coltype));
2256
            siz.y = tsiz.y = nextpoty;
4498 helixhorne 2257
 
5713 hendricks2 2258
            npoty = 1;
5712 hendricks2 2259
        }
4498 helixhorne 2260
 
6653 pogokeen 2261
        uploadtexture(doalloc, siz, GL_BGRA, pic, tsiz,
5712 hendricks2 2262
                      dameth | DAMETH_ARTIMMUNITY |
2263
                      (dapic >= MAXUSERTILES ? (DAMETH_NOTEXCOMPRESS|DAMETH_NODOWNSIZE) : 0) | /* never process these short-lived tiles */
5713 hendricks2 2264
                      (hasfullbright ? DAMETH_HASFULLBRIGHT : 0) |
2265
                      (npoty ? DAMETH_NPOTWALL : 0) |
5712 hendricks2 2266
                      (hasalpha ? (DAMETH_HASALPHA|DAMETH_ONEBITALPHA) : 0));
2267
 
7705 terminx 2268
        Xfree(pic);
4498 helixhorne 2269
    }
2270
 
5075 terminx 2271
    polymost_setuptexture(dameth, -1);
5001 terminx 2272
 
109 terminx 2273
    pth->picnum = dapic;
2274
    pth->palnum = dapal;
3761 terminx 2275
    pth->shade = dashade;
109 terminx 2276
    pth->effects = 0;
7612 pogokeen 2277
    pth->flags = TO_PTH_CLAMPED(dameth) | TO_PTH_NOTRANSFIX(dameth) | (hasalpha*(PTH_HASALPHA|PTH_ONEBITALPHA)) | (npoty*PTH_NPOTWALL);