mirror of
https://git.do.srb2.org/STJr/SRB2.git
synced 2024-11-21 20:11:12 +00:00
Merge branch 'next' into delete-unused-render-code
This commit is contained in:
commit
5a46f12c62
31 changed files with 2325 additions and 1064 deletions
|
@ -569,7 +569,7 @@ void F_RunWipe(UINT8 wipetype, boolean drawMenu)
|
|||
if (rendermode == render_opengl)
|
||||
{
|
||||
// send in the wipe type and wipe frame because we need to cache the graphic
|
||||
HWR_DoTintedWipe(wipetype, wipeframe-1);
|
||||
HWR_DoWipe(wipetype, wipeframe-1);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
|
|
@ -10,5 +10,6 @@ target_sources(SRB2SDL2 PRIVATE
|
|||
hw_md3load.c
|
||||
hw_model.c
|
||||
hw_batching.c
|
||||
hw_shaders.c
|
||||
r_opengl/r_opengl.c
|
||||
)
|
||||
|
|
|
@ -9,4 +9,5 @@ hw_md2load.c
|
|||
hw_md3load.c
|
||||
hw_model.c
|
||||
hw_batching.c
|
||||
hw_shaders.c
|
||||
r_opengl/r_opengl.c
|
||||
|
|
|
@ -76,7 +76,7 @@ void HWR_SetCurrentTexture(GLMipmap_t *texture)
|
|||
// If batching is enabled, this function collects the polygon data and the chosen texture
|
||||
// for later use in HWR_RenderBatches. Otherwise the rendering backend is used to
|
||||
// render the polygon immediately.
|
||||
void HWR_ProcessPolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPts, FBITFIELD PolyFlags, int shader, boolean horizonSpecial)
|
||||
void HWR_ProcessPolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPts, FBITFIELD PolyFlags, int shader_target, boolean horizonSpecial)
|
||||
{
|
||||
if (currently_batching)
|
||||
{
|
||||
|
@ -114,7 +114,7 @@ void HWR_ProcessPolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPt
|
|||
polygonArray[polygonArraySize].numVerts = iNumPts;
|
||||
polygonArray[polygonArraySize].polyFlags = PolyFlags;
|
||||
polygonArray[polygonArraySize].texture = current_texture;
|
||||
polygonArray[polygonArraySize].shader = shader;
|
||||
polygonArray[polygonArraySize].shader = (shader_target != -1) ? HWR_GetShaderFromTarget(shader_target) : shader_target;
|
||||
polygonArray[polygonArraySize].horizonSpecial = horizonSpecial;
|
||||
// default to polygonArraySize so we don't lose order on horizon lines
|
||||
// (yes, it's supposed to be negative, since we're sorting in that direction)
|
||||
|
@ -134,7 +134,7 @@ void HWR_ProcessPolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPt
|
|||
DIGEST(hash, pSurf->PolyColor.rgba);
|
||||
if (cv_glshaders.value && gl_shadersavailable)
|
||||
{
|
||||
DIGEST(hash, shader);
|
||||
DIGEST(hash, shader_target);
|
||||
DIGEST(hash, pSurf->TintColor.rgba);
|
||||
DIGEST(hash, pSurf->FadeColor.rgba);
|
||||
DIGEST(hash, pSurf->LightInfo.light_level);
|
||||
|
@ -151,10 +151,9 @@ void HWR_ProcessPolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPt
|
|||
}
|
||||
else
|
||||
{
|
||||
if (shader)
|
||||
HWD.pfnSetShader(shader);
|
||||
HWD.pfnDrawPolygon(pSurf, pOutVerts, iNumPts, PolyFlags);
|
||||
}
|
||||
HWD.pfnSetShader((shader_target != SHADER_NONE) ? HWR_GetShaderFromTarget(shader_target) : shader_target);
|
||||
HWD.pfnDrawPolygon(pSurf, pOutVerts, iNumPts, PolyFlags);
|
||||
}
|
||||
}
|
||||
|
||||
static int comparePolygons(const void *p1, const void *p2)
|
||||
|
|
|
@ -32,6 +32,14 @@
|
|||
INT32 patchformat = GL_TEXFMT_AP_88; // use alpha for holes
|
||||
INT32 textureformat = GL_TEXFMT_P_8; // use chromakey for hole
|
||||
|
||||
RGBA_t mapPalette[256] = {0}; // the palette for the currently loaded level or menu etc.
|
||||
|
||||
// Returns a pointer to the palette which should be used for caching textures.
|
||||
RGBA_t *HWR_GetTexturePalette(void)
|
||||
{
|
||||
return HWR_ShouldUsePaletteRendering() ? mapPalette : pLocalPalette;
|
||||
}
|
||||
|
||||
static INT32 format2bpp(GLTextureFormat_t format)
|
||||
{
|
||||
if (format == GL_TEXFMT_RGBA)
|
||||
|
@ -49,7 +57,7 @@ static void HWR_DrawColumnInCache(const column_t *patchcol, UINT8 *block, GLMipm
|
|||
INT32 pblockheight, INT32 blockmodulo,
|
||||
fixed_t yfracstep, fixed_t scale_y,
|
||||
texpatch_t *originPatch, INT32 patchheight,
|
||||
INT32 bpp)
|
||||
INT32 bpp, RGBA_t *palette)
|
||||
{
|
||||
fixed_t yfrac, position, count;
|
||||
UINT8 *dest;
|
||||
|
@ -113,7 +121,7 @@ static void HWR_DrawColumnInCache(const column_t *patchcol, UINT8 *block, GLMipm
|
|||
memcpy(dest, &texelu16, sizeof(UINT16));
|
||||
break;
|
||||
case 3:
|
||||
colortemp = V_GetColor(texel);
|
||||
colortemp = palette[texel];
|
||||
if ((originPatch != NULL) && (originPatch->style != AST_COPY))
|
||||
{
|
||||
RGBA_t rgbatexel;
|
||||
|
@ -123,7 +131,7 @@ static void HWR_DrawColumnInCache(const column_t *patchcol, UINT8 *block, GLMipm
|
|||
memcpy(dest, &colortemp, sizeof(RGBA_t)-sizeof(UINT8));
|
||||
break;
|
||||
case 4:
|
||||
colortemp = V_GetColor(texel);
|
||||
colortemp = palette[texel];
|
||||
colortemp.s.alpha = alpha;
|
||||
if ((originPatch != NULL) && (originPatch->style != AST_COPY))
|
||||
{
|
||||
|
@ -152,7 +160,7 @@ static void HWR_DrawFlippedColumnInCache(const column_t *patchcol, UINT8 *block,
|
|||
INT32 pblockheight, INT32 blockmodulo,
|
||||
fixed_t yfracstep, fixed_t scale_y,
|
||||
texpatch_t *originPatch, INT32 patchheight,
|
||||
INT32 bpp)
|
||||
INT32 bpp, RGBA_t *palette)
|
||||
{
|
||||
fixed_t yfrac, position, count;
|
||||
UINT8 *dest;
|
||||
|
@ -217,7 +225,7 @@ static void HWR_DrawFlippedColumnInCache(const column_t *patchcol, UINT8 *block,
|
|||
memcpy(dest, &texelu16, sizeof(UINT16));
|
||||
break;
|
||||
case 3:
|
||||
colortemp = V_GetColor(texel);
|
||||
colortemp = palette[texel];
|
||||
if ((originPatch != NULL) && (originPatch->style != AST_COPY))
|
||||
{
|
||||
RGBA_t rgbatexel;
|
||||
|
@ -227,7 +235,7 @@ static void HWR_DrawFlippedColumnInCache(const column_t *patchcol, UINT8 *block,
|
|||
memcpy(dest, &colortemp, sizeof(RGBA_t)-sizeof(UINT8));
|
||||
break;
|
||||
case 4:
|
||||
colortemp = V_GetColor(texel);
|
||||
colortemp = palette[texel];
|
||||
colortemp.s.alpha = alpha;
|
||||
if ((originPatch != NULL) && (originPatch->style != AST_COPY))
|
||||
{
|
||||
|
@ -269,10 +277,13 @@ static void HWR_DrawPatchInCache(GLMipmap_t *mipmap,
|
|||
UINT8 *block = mipmap->data;
|
||||
INT32 bpp;
|
||||
INT32 blockmodulo;
|
||||
RGBA_t *palette;
|
||||
|
||||
if (pwidth <= 0 || pheight <= 0)
|
||||
return;
|
||||
|
||||
palette = HWR_GetTexturePalette();
|
||||
|
||||
ncols = pwidth;
|
||||
|
||||
// source advance
|
||||
|
@ -298,7 +309,7 @@ static void HWR_DrawPatchInCache(GLMipmap_t *mipmap,
|
|||
pblockheight, blockmodulo,
|
||||
yfracstep, scale_y,
|
||||
NULL, pheight, // not that pheight is going to get used anyway...
|
||||
bpp);
|
||||
bpp, palette);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -317,16 +328,19 @@ static void HWR_DrawTexturePatchInCache(GLMipmap_t *mipmap,
|
|||
INT32 bpp;
|
||||
INT32 blockmodulo;
|
||||
INT32 width, height;
|
||||
RGBA_t *palette;
|
||||
// Column drawing function pointer.
|
||||
static void (*ColumnDrawerPointer)(const column_t *patchcol, UINT8 *block, GLMipmap_t *mipmap,
|
||||
INT32 pblockheight, INT32 blockmodulo,
|
||||
fixed_t yfracstep, fixed_t scale_y,
|
||||
texpatch_t *originPatch, INT32 patchheight,
|
||||
INT32 bpp);
|
||||
INT32 bpp, RGBA_t *palette);
|
||||
|
||||
if (texture->width <= 0 || texture->height <= 0)
|
||||
return;
|
||||
|
||||
palette = HWR_GetTexturePalette();
|
||||
|
||||
ColumnDrawerPointer = (patch->flip & 2) ? HWR_DrawFlippedColumnInCache : HWR_DrawColumnInCache;
|
||||
|
||||
x1 = patch->originx;
|
||||
|
@ -386,7 +400,7 @@ static void HWR_DrawTexturePatchInCache(GLMipmap_t *mipmap,
|
|||
pblockheight, blockmodulo,
|
||||
yfracstep, scale_y,
|
||||
patch, height,
|
||||
bpp);
|
||||
bpp, palette);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -429,6 +443,9 @@ static void HWR_GenerateTexture(INT32 texnum, GLMapTexture_t *grtex)
|
|||
INT32 i;
|
||||
boolean skyspecial = false; //poor hack for Legacy large skies..
|
||||
|
||||
RGBA_t *palette;
|
||||
palette = HWR_GetTexturePalette();
|
||||
|
||||
texture = textures[texnum];
|
||||
|
||||
// hack the Legacy skies..
|
||||
|
@ -447,7 +464,10 @@ static void HWR_GenerateTexture(INT32 texnum, GLMapTexture_t *grtex)
|
|||
|
||||
grtex->mipmap.width = (UINT16)texture->width;
|
||||
grtex->mipmap.height = (UINT16)texture->height;
|
||||
grtex->mipmap.format = textureformat;
|
||||
if (skyspecial)
|
||||
grtex->mipmap.format = GL_TEXFMT_RGBA; // that skyspecial code below assumes this format ...
|
||||
else
|
||||
grtex->mipmap.format = textureformat;
|
||||
|
||||
blockwidth = texture->width;
|
||||
blockheight = texture->height;
|
||||
|
@ -459,7 +479,7 @@ static void HWR_GenerateTexture(INT32 texnum, GLMapTexture_t *grtex)
|
|||
INT32 j;
|
||||
RGBA_t col;
|
||||
|
||||
col = V_GetColor(HWR_PATCHES_CHROMAKEY_COLORINDEX);
|
||||
col = palette[HWR_PATCHES_CHROMAKEY_COLORINDEX];
|
||||
for (j = 0; j < blockheight; j++)
|
||||
{
|
||||
for (i = 0; i < blockwidth; i++)
|
||||
|
@ -739,19 +759,6 @@ void HWR_LoadMapTextures(size_t pnumtextures)
|
|||
gl_maptexturesloaded = true;
|
||||
}
|
||||
|
||||
void HWR_SetPalette(RGBA_t *palette)
|
||||
{
|
||||
HWD.pfnSetPalette(palette);
|
||||
|
||||
// hardware driver will flush there own cache if cache is non paletized
|
||||
// now flush data texture cache so 32 bit texture are recomputed
|
||||
if (patchformat == GL_TEXFMT_RGBA || textureformat == GL_TEXFMT_RGBA)
|
||||
{
|
||||
Z_FreeTag(PU_HWRCACHE);
|
||||
Z_FreeTag(PU_HWRCACHE_UNLOCKED);
|
||||
}
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Make sure texture is downloaded and set it as the source
|
||||
// --------------------------------------------------------------------------
|
||||
|
@ -965,6 +972,139 @@ void HWR_UnlockCachedPatch(GLPatch_t *gpatch)
|
|||
Z_ChangeTag(gpatch->mipmap->data, PU_HWRCACHE_UNLOCKED);
|
||||
}
|
||||
|
||||
static const INT32 picmode2GR[] =
|
||||
{
|
||||
GL_TEXFMT_P_8, // PALETTE
|
||||
0, // INTENSITY (unsupported yet)
|
||||
GL_TEXFMT_ALPHA_INTENSITY_88, // INTENSITY_ALPHA (corona use this)
|
||||
0, // RGB24 (unsupported yet)
|
||||
GL_TEXFMT_RGBA, // RGBA32 (opengl only)
|
||||
};
|
||||
|
||||
static void HWR_DrawPicInCache(UINT8 *block, INT32 pblockwidth, INT32 pblockheight,
|
||||
INT32 blockmodulo, pic_t *pic, INT32 bpp)
|
||||
{
|
||||
INT32 i,j;
|
||||
fixed_t posx, posy, stepx, stepy;
|
||||
UINT8 *dest, *src, texel;
|
||||
UINT16 texelu16;
|
||||
INT32 picbpp;
|
||||
RGBA_t col;
|
||||
RGBA_t *palette = HWR_GetTexturePalette();
|
||||
|
||||
stepy = ((INT32)SHORT(pic->height)<<FRACBITS)/pblockheight;
|
||||
stepx = ((INT32)SHORT(pic->width)<<FRACBITS)/pblockwidth;
|
||||
picbpp = format2bpp(picmode2GR[pic->mode]);
|
||||
posy = 0;
|
||||
for (j = 0; j < pblockheight; j++)
|
||||
{
|
||||
posx = 0;
|
||||
dest = &block[j*blockmodulo];
|
||||
src = &pic->data[(posy>>FRACBITS)*SHORT(pic->width)*picbpp];
|
||||
for (i = 0; i < pblockwidth;i++)
|
||||
{
|
||||
switch (pic->mode)
|
||||
{ // source bpp
|
||||
case PALETTE :
|
||||
texel = src[(posx+FRACUNIT/2)>>FRACBITS];
|
||||
switch (bpp)
|
||||
{ // destination bpp
|
||||
case 1 :
|
||||
*dest++ = texel; break;
|
||||
case 2 :
|
||||
texelu16 = (UINT16)(texel | 0xff00);
|
||||
memcpy(dest, &texelu16, sizeof(UINT16));
|
||||
dest += sizeof(UINT16);
|
||||
break;
|
||||
case 3 :
|
||||
col = palette[texel];
|
||||
memcpy(dest, &col, sizeof(RGBA_t)-sizeof(UINT8));
|
||||
dest += sizeof(RGBA_t)-sizeof(UINT8);
|
||||
break;
|
||||
case 4 :
|
||||
memcpy(dest, &palette[texel], sizeof(RGBA_t));
|
||||
dest += sizeof(RGBA_t);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case INTENSITY :
|
||||
*dest++ = src[(posx+FRACUNIT/2)>>FRACBITS];
|
||||
break;
|
||||
case INTENSITY_ALPHA : // assume dest bpp = 2
|
||||
memcpy(dest, src + ((posx+FRACUNIT/2)>>FRACBITS)*sizeof(UINT16), sizeof(UINT16));
|
||||
dest += sizeof(UINT16);
|
||||
break;
|
||||
case RGB24 :
|
||||
break; // not supported yet
|
||||
case RGBA32 : // assume dest bpp = 4
|
||||
dest += sizeof(UINT32);
|
||||
memcpy(dest, src + ((posx+FRACUNIT/2)>>FRACBITS)*sizeof(UINT32), sizeof(UINT32));
|
||||
break;
|
||||
}
|
||||
posx += stepx;
|
||||
}
|
||||
posy += stepy;
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------+
|
||||
// HWR_GetPic : Download a Doom pic (raw row encoded with no 'holes')
|
||||
// Returns :
|
||||
// -----------------+
|
||||
patch_t *HWR_GetPic(lumpnum_t lumpnum)
|
||||
{
|
||||
patch_t *patch = HWR_GetCachedGLPatch(lumpnum);
|
||||
GLPatch_t *grPatch = (GLPatch_t *)(patch->hardware);
|
||||
|
||||
if (!grPatch->mipmap->downloaded && !grPatch->mipmap->data)
|
||||
{
|
||||
pic_t *pic;
|
||||
UINT8 *block;
|
||||
size_t len;
|
||||
|
||||
pic = W_CacheLumpNum(lumpnum, PU_CACHE);
|
||||
patch->width = SHORT(pic->width);
|
||||
patch->height = SHORT(pic->height);
|
||||
len = W_LumpLength(lumpnum) - sizeof (pic_t);
|
||||
|
||||
grPatch->mipmap->width = (UINT16)patch->width;
|
||||
grPatch->mipmap->height = (UINT16)patch->height;
|
||||
|
||||
if (pic->mode == PALETTE)
|
||||
grPatch->mipmap->format = textureformat; // can be set by driver
|
||||
else
|
||||
grPatch->mipmap->format = picmode2GR[pic->mode];
|
||||
|
||||
Z_Free(grPatch->mipmap->data);
|
||||
|
||||
// allocate block
|
||||
block = MakeBlock(grPatch->mipmap);
|
||||
|
||||
if (patch->width == SHORT(pic->width) &&
|
||||
patch->height == SHORT(pic->height) &&
|
||||
format2bpp(grPatch->mipmap->format) == format2bpp(picmode2GR[pic->mode]))
|
||||
{
|
||||
// no conversion needed
|
||||
M_Memcpy(grPatch->mipmap->data, pic->data,len);
|
||||
}
|
||||
else
|
||||
HWR_DrawPicInCache(block, SHORT(pic->width), SHORT(pic->height),
|
||||
SHORT(pic->width)*format2bpp(grPatch->mipmap->format),
|
||||
pic,
|
||||
format2bpp(grPatch->mipmap->format));
|
||||
|
||||
Z_Unlock(pic);
|
||||
Z_ChangeTag(block, PU_HWRCACHE_UNLOCKED);
|
||||
|
||||
grPatch->mipmap->flags = 0;
|
||||
grPatch->max_s = grPatch->max_t = 1.0f;
|
||||
}
|
||||
HWD.pfnSetTexture(grPatch->mipmap);
|
||||
//CONS_Debug(DBG_RENDER, "picloaded at %x as texture %d\n",grPatch->mipmap->data, grPatch->mipmap->downloaded);
|
||||
|
||||
return patch;
|
||||
}
|
||||
|
||||
patch_t *HWR_GetCachedGLPatchPwad(UINT16 wadnum, UINT16 lumpnum)
|
||||
{
|
||||
lumpcache_t *lumpcache = wadfiles[wadnum]->patchcache;
|
||||
|
@ -992,6 +1132,7 @@ static void HWR_DrawFadeMaskInCache(GLMipmap_t *mipmap, INT32 pblockwidth, INT32
|
|||
UINT8 *flat;
|
||||
UINT8 *dest, *src, texel;
|
||||
RGBA_t col;
|
||||
RGBA_t *palette = HWR_GetTexturePalette();
|
||||
|
||||
// Place the flats data into flat
|
||||
W_ReadLump(fademasklumpnum, Z_Malloc(W_LumpLength(fademasklumpnum),
|
||||
|
@ -1009,7 +1150,7 @@ static void HWR_DrawFadeMaskInCache(GLMipmap_t *mipmap, INT32 pblockwidth, INT32
|
|||
{
|
||||
// fademask bpp is always 1, and is used just for alpha
|
||||
texel = src[(posx)>>FRACBITS];
|
||||
col = V_GetColor(texel);
|
||||
col = palette[texel];
|
||||
*dest = col.s.red; // take the red level of the colour and use it for alpha, as fademasks do
|
||||
|
||||
dest++;
|
||||
|
@ -1081,4 +1222,185 @@ void HWR_GetFadeMask(lumpnum_t fademasklumpnum)
|
|||
Z_ChangeTag(grmip->data, PU_HWRCACHE_UNLOCKED);
|
||||
}
|
||||
|
||||
// =================================================
|
||||
// PALETTE HANDLING
|
||||
// =================================================
|
||||
|
||||
void HWR_SetPalette(RGBA_t *palette)
|
||||
{
|
||||
if (HWR_ShouldUsePaletteRendering())
|
||||
{
|
||||
// set the palette for palette postprocessing
|
||||
|
||||
if (cv_glpalettedepth.value == 16)
|
||||
{
|
||||
// crush to 16-bit rgb565, like software currently does in the standard configuration
|
||||
// Note: Software's screenshots have the 24-bit palette, but the screen gets
|
||||
// the 16-bit version! For making comparison screenshots either use an external screenshot
|
||||
// tool or set the palette depth to 24 bits.
|
||||
RGBA_t crushed_palette[256];
|
||||
int i;
|
||||
for (i = 0; i < 256; i++)
|
||||
{
|
||||
float fred = (float)(palette[i].s.red >> 3);
|
||||
float fgreen = (float)(palette[i].s.green >> 2);
|
||||
float fblue = (float)(palette[i].s.blue >> 3);
|
||||
crushed_palette[i].s.red = (UINT8)(fred / 31.0f * 255.0f);
|
||||
crushed_palette[i].s.green = (UINT8)(fgreen / 63.0f * 255.0f);
|
||||
crushed_palette[i].s.blue = (UINT8)(fblue / 31.0f * 255.0f);
|
||||
crushed_palette[i].s.alpha = 255;
|
||||
}
|
||||
HWD.pfnSetScreenPalette(crushed_palette);
|
||||
}
|
||||
else
|
||||
{
|
||||
HWD.pfnSetScreenPalette(palette);
|
||||
}
|
||||
|
||||
// this part is responsible for keeping track of the palette OUTSIDE of a level.
|
||||
if (!(gamestate == GS_LEVEL || (gamestate == GS_TITLESCREEN && titlemapinaction)))
|
||||
HWR_SetMapPalette();
|
||||
}
|
||||
else
|
||||
{
|
||||
// set the palette for the textures
|
||||
HWD.pfnSetTexturePalette(palette);
|
||||
// reset mapPalette so next call to HWR_SetMapPalette will update everything correctly
|
||||
memset(mapPalette, 0, sizeof(mapPalette));
|
||||
// hardware driver will flush there own cache if cache is non paletized
|
||||
// now flush data texture cache so 32 bit texture are recomputed
|
||||
if (patchformat == GL_TEXFMT_RGBA || textureformat == GL_TEXFMT_RGBA)
|
||||
{
|
||||
Z_FreeTag(PU_HWRCACHE);
|
||||
Z_FreeTag(PU_HWRCACHE_UNLOCKED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void HWR_SetPaletteLookup(RGBA_t *palette)
|
||||
{
|
||||
int r, g, b;
|
||||
UINT8 *lut = Z_Malloc(
|
||||
HWR_PALETTE_LUT_SIZE*HWR_PALETTE_LUT_SIZE*HWR_PALETTE_LUT_SIZE*sizeof(UINT8),
|
||||
PU_STATIC, NULL);
|
||||
#define STEP_SIZE (256/HWR_PALETTE_LUT_SIZE)
|
||||
for (b = 0; b < HWR_PALETTE_LUT_SIZE; b++)
|
||||
{
|
||||
for (g = 0; g < HWR_PALETTE_LUT_SIZE; g++)
|
||||
{
|
||||
for (r = 0; r < HWR_PALETTE_LUT_SIZE; r++)
|
||||
{
|
||||
lut[b*HWR_PALETTE_LUT_SIZE*HWR_PALETTE_LUT_SIZE+g*HWR_PALETTE_LUT_SIZE+r] =
|
||||
NearestPaletteColor(r*STEP_SIZE, g*STEP_SIZE, b*STEP_SIZE, palette);
|
||||
}
|
||||
}
|
||||
}
|
||||
#undef STEP_SIZE
|
||||
HWD.pfnSetPaletteLookup(lut);
|
||||
Z_Free(lut);
|
||||
}
|
||||
|
||||
// Updates mapPalette to reflect the loaded level or other game state.
|
||||
// Textures are flushed if needed.
|
||||
// Call this function only in palette rendering mode.
|
||||
void HWR_SetMapPalette(void)
|
||||
{
|
||||
RGBA_t RGBA_converted[256];
|
||||
RGBA_t *palette;
|
||||
int i;
|
||||
|
||||
if (!(gamestate == GS_LEVEL || (gamestate == GS_TITLESCREEN && titlemapinaction)))
|
||||
{
|
||||
// outside of a level, pMasterPalette should have PLAYPAL ready for us
|
||||
palette = pMasterPalette;
|
||||
}
|
||||
else
|
||||
{
|
||||
// in a level pMasterPalette might have a flash palette, but we
|
||||
// want the map's original palette.
|
||||
lumpnum_t lumpnum = W_GetNumForName(GetPalette());
|
||||
size_t palsize = W_LumpLength(lumpnum);
|
||||
UINT8 *RGB_data;
|
||||
if (palsize < 768) // 256 * 3
|
||||
I_Error("HWR_SetMapPalette: A programmer assumed palette lumps are at least 768 bytes long, but apparently this was a wrong assumption!\n");
|
||||
RGB_data = W_CacheLumpNum(lumpnum, PU_CACHE);
|
||||
// we got the RGB palette now, but we need it in RGBA format.
|
||||
for (i = 0; i < 256; i++)
|
||||
{
|
||||
RGBA_converted[i].s.red = *(RGB_data++);
|
||||
RGBA_converted[i].s.green = *(RGB_data++);
|
||||
RGBA_converted[i].s.blue = *(RGB_data++);
|
||||
RGBA_converted[i].s.alpha = 255;
|
||||
}
|
||||
palette = RGBA_converted;
|
||||
}
|
||||
|
||||
// check if the palette has changed from the previous one
|
||||
if (memcmp(mapPalette, palette, sizeof(mapPalette)))
|
||||
{
|
||||
memcpy(mapPalette, palette, sizeof(mapPalette));
|
||||
// in palette rendering mode, this means that all rgba textures now have wrong colors
|
||||
// and the lookup table is outdated
|
||||
HWR_SetPaletteLookup(mapPalette);
|
||||
HWD.pfnSetTexturePalette(mapPalette);
|
||||
if (patchformat == GL_TEXFMT_RGBA || textureformat == GL_TEXFMT_RGBA)
|
||||
{
|
||||
Z_FreeTag(PU_HWRCACHE);
|
||||
Z_FreeTag(PU_HWRCACHE_UNLOCKED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Creates a hardware lighttable from the supplied lighttable.
|
||||
// Returns the id of the hw lighttable, usable in FSurfaceInfo.
|
||||
UINT32 HWR_CreateLightTable(UINT8 *lighttable)
|
||||
{
|
||||
UINT32 i, id;
|
||||
RGBA_t *palette = HWR_GetTexturePalette();
|
||||
RGBA_t *hw_lighttable = Z_Malloc(256 * 32 * sizeof(RGBA_t), PU_STATIC, NULL);
|
||||
|
||||
// To make the palette index -> RGBA mapping easier for the shader,
|
||||
// the hardware lighttable is composed of RGBA colors instead of palette indices.
|
||||
for (i = 0; i < 256 * 32; i++)
|
||||
hw_lighttable[i] = palette[lighttable[i]];
|
||||
|
||||
id = HWD.pfnCreateLightTable(hw_lighttable);
|
||||
Z_Free(hw_lighttable);
|
||||
return id;
|
||||
}
|
||||
|
||||
// get hwr lighttable id for colormap, create it if it doesn't already exist
|
||||
UINT32 HWR_GetLightTableID(extracolormap_t *colormap)
|
||||
{
|
||||
boolean default_colormap = false;
|
||||
if (!colormap)
|
||||
{
|
||||
colormap = R_GetDefaultColormap(); // a place to store the hw lighttable id
|
||||
// alternatively could just store the id in a global variable if there are issues
|
||||
default_colormap = true;
|
||||
}
|
||||
|
||||
// create hw lighttable if there isn't one
|
||||
if (!colormap->gl_lighttable_id)
|
||||
{
|
||||
UINT8 *colormap_pointer;
|
||||
|
||||
if (default_colormap)
|
||||
colormap_pointer = colormaps; // don't actually use the data from the "default colormap"
|
||||
else
|
||||
colormap_pointer = colormap->colormap;
|
||||
colormap->gl_lighttable_id = HWR_CreateLightTable(colormap_pointer);
|
||||
}
|
||||
|
||||
return colormap->gl_lighttable_id;
|
||||
}
|
||||
|
||||
// Note: all hardware lighttable ids assigned before this
|
||||
// call become invalid and must not be used.
|
||||
void HWR_ClearLightTables(void)
|
||||
{
|
||||
if (vid.glstate == VID_GL_LIBRARY_LOADED)
|
||||
HWD.pfnClearLightTables();
|
||||
}
|
||||
|
||||
#endif //HWRENDER
|
||||
|
|
|
@ -18,6 +18,12 @@
|
|||
#define ZCLIP_PLANE 4.0f // Used for the actual game drawing
|
||||
#define NZCLIP_PLANE 0.9f // Seems to be only used for the HUD and screen textures
|
||||
|
||||
// The width/height/depth of the palette lookup table used by palette rendering.
|
||||
// Changing this also requires changing the shader code!
|
||||
// Also assumed to be a power of two in some parts of the code.
|
||||
// 64 seems to work perfectly for the vanilla palette.
|
||||
#define HWR_PALETTE_LUT_SIZE 64
|
||||
|
||||
// ==========================================================================
|
||||
// SIMPLE TYPES
|
||||
// ==========================================================================
|
||||
|
@ -122,33 +128,31 @@ typedef struct
|
|||
} FOutVector;
|
||||
|
||||
#ifdef GL_SHADERS
|
||||
// Predefined shader types
|
||||
|
||||
// Shader targets used to render specific types of geometry.
|
||||
// A shader target is resolved to an actual shader with HWR_GetShaderFromTarget.
|
||||
// The shader returned may be a base shader or a custom shader.
|
||||
enum
|
||||
{
|
||||
SHADER_NONE = -1,
|
||||
SHADER_DEFAULT = 0,
|
||||
|
||||
SHADER_FLOOR,
|
||||
SHADER_FLOOR = 0,
|
||||
SHADER_WALL,
|
||||
SHADER_SPRITE,
|
||||
SHADER_MODEL, SHADER_MODEL_LIGHTING,
|
||||
SHADER_MODEL,
|
||||
SHADER_WATER,
|
||||
SHADER_FOG,
|
||||
SHADER_SKY,
|
||||
SHADER_PALETTE_POSTPROCESS,
|
||||
SHADER_UI_COLORMAP_FADE,
|
||||
SHADER_UI_TINTED_WIPE,
|
||||
|
||||
NUMBASESHADERS,
|
||||
NUMSHADERTARGETS
|
||||
};
|
||||
|
||||
// Maximum amount of shader programs
|
||||
// Must be higher than NUMBASESHADERS
|
||||
#define HWR_MAXSHADERS 16
|
||||
|
||||
// Shader sources (vertex and fragment)
|
||||
typedef struct
|
||||
{
|
||||
char *vertex;
|
||||
char *fragment;
|
||||
} shadersource_t;
|
||||
// Must be at least NUMSHADERTARGETS*2 to fit base and custom shaders for each shader target.
|
||||
#define HWR_MAXSHADERS NUMSHADERTARGETS*2
|
||||
|
||||
// Custom shader reference table
|
||||
typedef struct
|
||||
|
@ -272,11 +276,15 @@ struct FSurfaceInfo
|
|||
RGBA_t PolyColor;
|
||||
RGBA_t TintColor;
|
||||
RGBA_t FadeColor;
|
||||
UINT32 LightTableId;
|
||||
FLightInfo LightInfo;
|
||||
};
|
||||
typedef struct FSurfaceInfo FSurfaceInfo;
|
||||
|
||||
//Hurdler: added for backward compatibility
|
||||
#define GL_DEFAULTMIX 0x00000000
|
||||
#define GL_DEFAULTFOG 0xFF000000
|
||||
|
||||
// Various settings and states for the rendering backend.
|
||||
enum hwdsetspecialstate
|
||||
{
|
||||
HWD_SET_MODEL_LIGHTING = 1,
|
||||
|
@ -289,15 +297,13 @@ enum hwdsetspecialstate
|
|||
|
||||
typedef enum hwdsetspecialstate hwdspecialstate_t;
|
||||
|
||||
// Lactozilla: Shader options
|
||||
enum hwdshaderoption
|
||||
enum hwdshaderstage
|
||||
{
|
||||
HWD_SHADEROPTION_OFF,
|
||||
HWD_SHADEROPTION_ON,
|
||||
HWD_SHADEROPTION_NOCUSTOM,
|
||||
HWD_SHADERSTAGE_VERTEX,
|
||||
HWD_SHADERSTAGE_FRAGMENT,
|
||||
};
|
||||
|
||||
typedef enum hwdshaderoption hwdshaderoption_t;
|
||||
typedef enum hwdshaderstage hwdshaderstage_t;
|
||||
|
||||
// Lactozilla: Shader info
|
||||
// Generally set at the start of the frame.
|
||||
|
@ -318,5 +324,18 @@ enum hwdfiltermode
|
|||
HWD_SET_TEXTUREFILTER_MIXED3,
|
||||
};
|
||||
|
||||
// Screen texture slots
|
||||
enum hwdscreentexture
|
||||
{
|
||||
HWD_SCREENTEXTURE_WIPE_START, // source image for the wipe/fade effect
|
||||
HWD_SCREENTEXTURE_WIPE_END, // destination image for the wipe/fade effect
|
||||
HWD_SCREENTEXTURE_GENERIC1, // underwater/heat effect, intermission background
|
||||
HWD_SCREENTEXTURE_GENERIC2, // palette-based colormap fade, screen before palette rendering's postprocessing
|
||||
HWD_SCREENTEXTURE_GENERIC3, // screen after palette rendering's postprocessing
|
||||
NUMSCREENTEXTURES, // (generic3 is unused if palette rendering is disabled)
|
||||
};
|
||||
|
||||
typedef enum hwdscreentexture hwdscreentexture_t;
|
||||
|
||||
|
||||
#endif //_HWR_DEFS_
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include "../st_stuff.h"
|
||||
#include "../p_local.h" // stplyr
|
||||
#include "../g_game.h" // players
|
||||
#include "../f_finale.h" // fade color factors
|
||||
|
||||
#include <fcntl.h>
|
||||
#include "../i_video.h"
|
||||
|
@ -645,6 +646,7 @@ void HWR_FadeScreenMenuBack(UINT16 color, UINT8 strength)
|
|||
{
|
||||
FOutVector v[4];
|
||||
FSurfaceInfo Surf;
|
||||
FBITFIELD poly_flags = PF_NoTexture|PF_Modulated|PF_NoDepthTest;
|
||||
|
||||
v[0].x = v[3].x = -1.0f;
|
||||
v[2].x = v[1].x = 1.0f;
|
||||
|
@ -657,17 +659,59 @@ void HWR_FadeScreenMenuBack(UINT16 color, UINT8 strength)
|
|||
v[0].t = v[1].t = 1.0f;
|
||||
v[2].t = v[3].t = 0.0f;
|
||||
|
||||
if (color & 0xFF00) // Do COLORMAP fade.
|
||||
if (color & 0xFF00) // Special fade options
|
||||
{
|
||||
Surf.PolyColor.rgba = UINT2RGBA(0x01010160);
|
||||
Surf.PolyColor.s.alpha = (strength*8);
|
||||
UINT16 option = color & 0x0F00;
|
||||
if (option == 0x0A00 || option == 0x0B00) // Tinted fades
|
||||
{
|
||||
INT32 r, g, b;
|
||||
int fade = strength * 8;
|
||||
|
||||
r = FADEREDFACTOR*fade/10;
|
||||
g = FADEGREENFACTOR*fade/10;
|
||||
b = FADEBLUEFACTOR*fade/10;
|
||||
|
||||
Surf.PolyColor.s.red = min(r, 255);
|
||||
Surf.PolyColor.s.green = min(g, 255);
|
||||
Surf.PolyColor.s.blue = min(b, 255);
|
||||
Surf.PolyColor.s.alpha = 255;
|
||||
|
||||
if (option == 0x0A00) // Tinted subtractive fade
|
||||
poly_flags |= PF_ReverseSubtract;
|
||||
else if (option == 0x0B00) // Tinted additive fade
|
||||
poly_flags |= PF_Additive;
|
||||
}
|
||||
else // COLORMAP fade
|
||||
{
|
||||
if (HWR_ShouldUsePaletteRendering())
|
||||
{
|
||||
const hwdscreentexture_t scr_tex = HWD_SCREENTEXTURE_GENERIC2;
|
||||
|
||||
Surf.LightTableId = HWR_GetLightTableID(NULL);
|
||||
Surf.LightInfo.light_level = strength;
|
||||
HWD.pfnMakeScreenTexture(scr_tex);
|
||||
HWD.pfnSetShader(HWR_GetShaderFromTarget(SHADER_UI_COLORMAP_FADE));
|
||||
HWD.pfnDrawScreenTexture(scr_tex, &Surf, PF_ColorMapped|PF_NoDepthTest);
|
||||
HWD.pfnUnSetShader();
|
||||
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
Surf.PolyColor.rgba = UINT2RGBA(0x01010160);
|
||||
Surf.PolyColor.s.alpha = (strength*8);
|
||||
poly_flags |= PF_Translucent;
|
||||
}
|
||||
}
|
||||
}
|
||||
else // Do TRANSMAP** fade.
|
||||
{
|
||||
Surf.PolyColor.rgba = V_GetColor(color).rgba;
|
||||
RGBA_t *palette = HWR_GetTexturePalette();
|
||||
Surf.PolyColor.rgba = palette[color&0xFF].rgba;
|
||||
Surf.PolyColor.s.alpha = softwaretranstogl[strength];
|
||||
poly_flags |= PF_Translucent;
|
||||
}
|
||||
HWD.pfnDrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Modulated|PF_Translucent|PF_NoDepthTest);
|
||||
HWD.pfnDrawPolygon(&Surf, v, 4, poly_flags);
|
||||
}
|
||||
|
||||
// -----------------+
|
||||
|
@ -835,7 +879,8 @@ void HWR_DrawFadeFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color, UINT16 ac
|
|||
}
|
||||
else // Do TRANSMAP** fade.
|
||||
{
|
||||
Surf.PolyColor.rgba = V_GetColor(actualcolor).rgba;
|
||||
RGBA_t *palette = HWR_GetTexturePalette();
|
||||
Surf.PolyColor.rgba = palette[actualcolor&0xFF].rgba;
|
||||
Surf.PolyColor.s.alpha = softwaretranstogl[strength];
|
||||
}
|
||||
HWD.pfnDrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Modulated|PF_Translucent|PF_NoDepthTest);
|
||||
|
@ -910,8 +955,9 @@ void HWR_drawAMline(const fline_t *fl, INT32 color)
|
|||
{
|
||||
F2DCoord v1, v2;
|
||||
RGBA_t color_rgba;
|
||||
RGBA_t *palette = HWR_GetTexturePalette();
|
||||
|
||||
color_rgba = V_GetColor(color);
|
||||
color_rgba = palette[color&0xFF];
|
||||
|
||||
v1.x = ((float)fl->a.x-(vid.width/2.0f))*(2.0f/vid.width);
|
||||
v1.y = ((float)fl->a.y-(vid.height/2.0f))*(2.0f/vid.height);
|
||||
|
@ -1096,6 +1142,7 @@ void HWR_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color)
|
|||
FOutVector v[4];
|
||||
FSurfaceInfo Surf;
|
||||
float fx, fy, fw, fh;
|
||||
RGBA_t *palette = HWR_GetTexturePalette();
|
||||
UINT8 alphalevel = ((color & V_ALPHAMASK) >> V_ALPHASHIFT);
|
||||
|
||||
UINT8 perplayershuffle = 0;
|
||||
|
@ -1182,7 +1229,7 @@ void HWR_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color)
|
|||
{
|
||||
if (x == 0 && y == 0 && w == BASEVIDWIDTH && h == BASEVIDHEIGHT)
|
||||
{
|
||||
RGBA_t rgbaColour = V_GetColor(color);
|
||||
RGBA_t rgbaColour = palette[color&0xFF];
|
||||
FRGBAFloat clearColour;
|
||||
clearColour.red = (float)rgbaColour.s.red / 255;
|
||||
clearColour.green = (float)rgbaColour.s.green / 255;
|
||||
|
@ -1259,7 +1306,7 @@ void HWR_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color)
|
|||
v[0].t = v[1].t = 0.0f;
|
||||
v[2].t = v[3].t = 1.0f;
|
||||
|
||||
Surf.PolyColor = V_GetColor(color);
|
||||
Surf.PolyColor = palette[color&0xFF];
|
||||
|
||||
if (alphalevel)
|
||||
{
|
||||
|
@ -1347,11 +1394,12 @@ static inline boolean saveTGA(const char *file_name, void *buffer,
|
|||
UINT8 *HWR_GetScreenshot(void)
|
||||
{
|
||||
UINT8 *buf = malloc(vid.width * vid.height * 3 * sizeof (*buf));
|
||||
int tex = HWR_ShouldUsePaletteRendering() ? HWD_SCREENTEXTURE_GENERIC3 : HWD_SCREENTEXTURE_GENERIC2;
|
||||
|
||||
if (!buf)
|
||||
return NULL;
|
||||
// returns 24bit 888 RGB
|
||||
HWD.pfnReadRect(0, 0, vid.width, vid.height, vid.width * 3, (void *)buf);
|
||||
HWD.pfnReadScreenTexture(tex, (void *)buf);
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
@ -1359,6 +1407,7 @@ boolean HWR_Screenshot(const char *pathname)
|
|||
{
|
||||
boolean ret;
|
||||
UINT8 *buf = malloc(vid.width * vid.height * 3 * sizeof (*buf));
|
||||
int tex = HWR_ShouldUsePaletteRendering() ? HWD_SCREENTEXTURE_GENERIC3 : HWD_SCREENTEXTURE_GENERIC2;
|
||||
|
||||
if (!buf)
|
||||
{
|
||||
|
@ -1367,7 +1416,7 @@ boolean HWR_Screenshot(const char *pathname)
|
|||
}
|
||||
|
||||
// returns 24bit 888 RGB
|
||||
HWD.pfnReadRect(0, 0, vid.width, vid.height, vid.width * 3, (void *)buf);
|
||||
HWD.pfnReadScreenTexture(tex, (void *)buf);
|
||||
|
||||
#ifdef USE_PNG
|
||||
ret = M_SavePNG(pathname, buf, vid.width, vid.height, NULL);
|
||||
|
|
|
@ -29,7 +29,7 @@ EXPORT boolean HWRAPI(Init) (void);
|
|||
#ifndef HAVE_SDL
|
||||
EXPORT void HWRAPI(Shutdown) (void);
|
||||
#endif
|
||||
EXPORT void HWRAPI(SetPalette) (RGBA_t *ppal);
|
||||
EXPORT void HWRAPI(SetTexturePalette) (RGBA_t *ppal);
|
||||
EXPORT void HWRAPI(FinishUpdate) (INT32 waitvbl);
|
||||
EXPORT void HWRAPI(Draw2DLine) (F2DCoord *v1, F2DCoord *v2, RGBA_t Color);
|
||||
EXPORT void HWRAPI(DrawPolygon) (FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPts, FBITFIELD PolyFlags);
|
||||
|
@ -40,11 +40,10 @@ EXPORT void HWRAPI(ClearBuffer) (FBOOLEAN ColorMask, FBOOLEAN DepthMask, FRGBAFl
|
|||
EXPORT void HWRAPI(SetTexture) (GLMipmap_t *TexInfo);
|
||||
EXPORT void HWRAPI(UpdateTexture) (GLMipmap_t *TexInfo);
|
||||
EXPORT void HWRAPI(DeleteTexture) (GLMipmap_t *TexInfo);
|
||||
EXPORT void HWRAPI(ReadRect) (INT32 x, INT32 y, INT32 width, INT32 height, INT32 dst_stride, UINT16 *dst_data);
|
||||
EXPORT void HWRAPI(ReadScreenTexture) (int tex, UINT8 *dst_data);
|
||||
EXPORT void HWRAPI(GClipRect) (INT32 minx, INT32 miny, INT32 maxx, INT32 maxy, float nearclip);
|
||||
EXPORT void HWRAPI(ClearMipMapCache) (void);
|
||||
|
||||
//Hurdler: added for backward compatibility
|
||||
EXPORT void HWRAPI(SetSpecialState) (hwdspecialstate_t IdState, INT32 Value);
|
||||
|
||||
//Hurdler: added for new development
|
||||
|
@ -54,24 +53,26 @@ EXPORT void HWRAPI(SetTransform) (FTransform *ptransform);
|
|||
EXPORT INT32 HWRAPI(GetTextureUsed) (void);
|
||||
|
||||
EXPORT void HWRAPI(FlushScreenTextures) (void);
|
||||
EXPORT void HWRAPI(StartScreenWipe) (void);
|
||||
EXPORT void HWRAPI(EndScreenWipe) (void);
|
||||
EXPORT void HWRAPI(DoScreenWipe) (void);
|
||||
EXPORT void HWRAPI(DrawIntermissionBG) (void);
|
||||
EXPORT void HWRAPI(MakeScreenTexture) (void);
|
||||
EXPORT void HWRAPI(MakeScreenFinalTexture) (void);
|
||||
EXPORT void HWRAPI(DrawScreenFinalTexture) (int width, int height);
|
||||
EXPORT void HWRAPI(DoScreenWipe) (int wipeStart, int wipeEnd, FSurfaceInfo *surf, FBITFIELD polyFlags);
|
||||
EXPORT void HWRAPI(DrawScreenTexture) (int tex, FSurfaceInfo *surf, FBITFIELD polyflags);
|
||||
EXPORT void HWRAPI(MakeScreenTexture) (int tex);
|
||||
EXPORT void HWRAPI(DrawScreenFinalTexture) (int tex, int width, int height);
|
||||
|
||||
#define SCREENVERTS 10
|
||||
EXPORT void HWRAPI(PostImgRedraw) (float points[SCREENVERTS][SCREENVERTS][2]);
|
||||
|
||||
EXPORT boolean HWRAPI(CompileShaders) (void);
|
||||
EXPORT void HWRAPI(CleanShaders) (void);
|
||||
EXPORT void HWRAPI(SetShader) (int type);
|
||||
EXPORT boolean HWRAPI(InitShaders) (void);
|
||||
EXPORT void HWRAPI(LoadShader) (int slot, char *code, hwdshaderstage_t stage);
|
||||
EXPORT boolean HWRAPI(CompileShader) (int slot);
|
||||
EXPORT void HWRAPI(SetShader) (int slot);
|
||||
EXPORT void HWRAPI(UnSetShader) (void);
|
||||
|
||||
EXPORT void HWRAPI(SetShaderInfo) (hwdshaderinfo_t info, INT32 value);
|
||||
EXPORT void HWRAPI(LoadCustomShader) (int number, char *code, size_t size, boolean isfragment);
|
||||
|
||||
EXPORT void HWRAPI(SetPaletteLookup)(UINT8 *lut);
|
||||
EXPORT UINT32 HWRAPI(CreateLightTable)(RGBA_t *hw_lighttable);
|
||||
EXPORT void HWRAPI(ClearLightTables)(void);
|
||||
EXPORT void HWRAPI(SetScreenPalette)(RGBA_t *palette);
|
||||
|
||||
// ==========================================================================
|
||||
// HWR DRIVER OBJECT, FOR CLIENT PROGRAM
|
||||
|
@ -82,7 +83,7 @@ EXPORT void HWRAPI(LoadCustomShader) (int number, char *code, size_t size, boole
|
|||
struct hwdriver_s
|
||||
{
|
||||
Init pfnInit;
|
||||
SetPalette pfnSetPalette;
|
||||
SetTexturePalette pfnSetTexturePalette;
|
||||
FinishUpdate pfnFinishUpdate;
|
||||
Draw2DLine pfnDraw2DLine;
|
||||
DrawPolygon pfnDrawPolygon;
|
||||
|
@ -93,10 +94,10 @@ struct hwdriver_s
|
|||
SetTexture pfnSetTexture;
|
||||
UpdateTexture pfnUpdateTexture;
|
||||
DeleteTexture pfnDeleteTexture;
|
||||
ReadRect pfnReadRect;
|
||||
ReadScreenTexture pfnReadScreenTexture;
|
||||
GClipRect pfnGClipRect;
|
||||
ClearMipMapCache pfnClearMipMapCache;
|
||||
SetSpecialState pfnSetSpecialState;//Hurdler: added for backward compatibility
|
||||
SetSpecialState pfnSetSpecialState;
|
||||
DrawModel pfnDrawModel;
|
||||
CreateModelVBOs pfnCreateModelVBOs;
|
||||
SetTransform pfnSetTransform;
|
||||
|
@ -109,21 +110,23 @@ struct hwdriver_s
|
|||
#endif
|
||||
PostImgRedraw pfnPostImgRedraw;
|
||||
FlushScreenTextures pfnFlushScreenTextures;
|
||||
StartScreenWipe pfnStartScreenWipe;
|
||||
EndScreenWipe pfnEndScreenWipe;
|
||||
DoScreenWipe pfnDoScreenWipe;
|
||||
DrawIntermissionBG pfnDrawIntermissionBG;
|
||||
DrawScreenTexture pfnDrawScreenTexture;
|
||||
MakeScreenTexture pfnMakeScreenTexture;
|
||||
MakeScreenFinalTexture pfnMakeScreenFinalTexture;
|
||||
DrawScreenFinalTexture pfnDrawScreenFinalTexture;
|
||||
|
||||
CompileShaders pfnCompileShaders;
|
||||
CleanShaders pfnCleanShaders;
|
||||
InitShaders pfnInitShaders;
|
||||
LoadShader pfnLoadShader;
|
||||
CompileShader pfnCompileShader;
|
||||
SetShader pfnSetShader;
|
||||
UnSetShader pfnUnSetShader;
|
||||
|
||||
SetShaderInfo pfnSetShaderInfo;
|
||||
LoadCustomShader pfnLoadCustomShader;
|
||||
|
||||
SetPaletteLookup pfnSetPaletteLookup;
|
||||
CreateLightTable pfnCreateLightTable;
|
||||
ClearLightTables pfnClearLightTables;
|
||||
SetScreenPalette pfnSetScreenPalette;
|
||||
};
|
||||
|
||||
extern struct hwdriver_s hwdriver;
|
||||
|
|
|
@ -107,6 +107,8 @@ void HWR_FreeExtraSubsectors(void);
|
|||
// --------
|
||||
// hw_cache.c
|
||||
// --------
|
||||
RGBA_t *HWR_GetTexturePalette(void);
|
||||
|
||||
void HWR_InitMapTextures(void);
|
||||
void HWR_LoadMapTextures(size_t pnumtextures);
|
||||
void HWR_FreeMapTextures(void);
|
||||
|
@ -131,6 +133,10 @@ void HWR_FreeColormapCache(void);
|
|||
void HWR_UnlockCachedPatch(GLPatch_t *gpatch);
|
||||
|
||||
void HWR_SetPalette(RGBA_t *palette);
|
||||
void HWR_SetMapPalette(void);
|
||||
UINT32 HWR_CreateLightTable(UINT8 *lighttable);
|
||||
UINT32 HWR_GetLightTableID(extracolormap_t *colormap);
|
||||
void HWR_ClearLightTables(void);
|
||||
|
||||
|
||||
// --------
|
||||
|
@ -139,4 +145,18 @@ void HWR_SetPalette(RGBA_t *palette);
|
|||
extern INT32 patchformat;
|
||||
extern INT32 textureformat;
|
||||
|
||||
// --------
|
||||
// hw_shaders.c
|
||||
// --------
|
||||
boolean HWR_InitShaders(void);
|
||||
void HWR_CompileShaders(void);
|
||||
|
||||
int HWR_GetShaderFromTarget(int shader_target);
|
||||
|
||||
void HWR_LoadAllCustomShaders(void);
|
||||
void HWR_LoadCustomShadersFromFile(UINT16 wadnum, boolean PK3);
|
||||
const char *HWR_GetShaderName(INT32 shader);
|
||||
|
||||
extern customshaderxlat_t shaderxlat[];
|
||||
|
||||
#endif //_HW_GLOB_
|
||||
|
|
|
@ -75,22 +75,6 @@ static line_t *gl_linedef;
|
|||
static sector_t *gl_frontsector;
|
||||
static sector_t *gl_backsector;
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// STUFF FOR THE PROJECTION CODE
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
FTransform atransform;
|
||||
|
||||
static float gl_viewx, gl_viewy, gl_viewz;
|
||||
float gl_viewsin, gl_viewcos;
|
||||
|
||||
// For HWR_RotateSpritePolyToAim
|
||||
static float gl_viewludsin, gl_viewludcos;
|
||||
static float gl_fovlud;
|
||||
|
||||
static angle_t gl_aimingangle;
|
||||
static void HWR_SetTransformAiming(FTransform *trans, player_t *player, boolean skybox);
|
||||
|
||||
// Render stats
|
||||
ps_metric_t ps_hw_skyboxtime = {0};
|
||||
ps_metric_t ps_hw_nodesorttime = {0};
|
||||
|
@ -111,13 +95,35 @@ ps_metric_t ps_hw_batchdrawtime = {0};
|
|||
|
||||
boolean gl_init = false;
|
||||
boolean gl_maploaded = false;
|
||||
boolean gl_shadersavailable = true;
|
||||
boolean gl_sessioncommandsadded = false;
|
||||
// false if shaders have not been initialized yet, or if shaders are not available
|
||||
boolean gl_shadersavailable = false;
|
||||
|
||||
// Whether the internal state is set to palette rendering or not.
|
||||
static boolean gl_palette_rendering_state = false;
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// STUFF FOR THE PROJECTION CODE
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
FTransform atransform;
|
||||
|
||||
static float gl_viewx, gl_viewy, gl_viewz;
|
||||
float gl_viewsin, gl_viewcos;
|
||||
|
||||
// For HWR_RotateSpritePolyToAim
|
||||
static float gl_viewludsin, gl_viewludcos;
|
||||
static float gl_fovlud;
|
||||
|
||||
static angle_t gl_aimingangle;
|
||||
static void HWR_SetTransformAiming(FTransform *trans, player_t *player, boolean skybox);
|
||||
|
||||
// ==========================================================================
|
||||
// Lighting
|
||||
// ==========================================================================
|
||||
|
||||
static boolean HWR_UseShader(void)
|
||||
// Returns true if shaders can be used.
|
||||
boolean HWR_UseShader(void)
|
||||
{
|
||||
return (cv_glshaders.value && gl_shadersavailable);
|
||||
}
|
||||
|
@ -183,6 +189,11 @@ void HWR_Lighting(FSurfaceInfo *Surface, INT32 light_level, extracolormap_t *col
|
|||
Surface->LightInfo.light_level = light_level;
|
||||
Surface->LightInfo.fade_start = (colormap != NULL) ? colormap->fadestart : 0;
|
||||
Surface->LightInfo.fade_end = (colormap != NULL) ? colormap->fadeend : 31;
|
||||
|
||||
if (HWR_ShouldUsePaletteRendering())
|
||||
Surface->LightTableId = HWR_GetLightTableID(colormap);
|
||||
else
|
||||
Surface->LightTableId = 0;
|
||||
}
|
||||
|
||||
UINT8 HWR_FogBlockAlpha(INT32 light, extracolormap_t *colormap) // Let's see if this can work
|
||||
|
@ -311,7 +322,7 @@ static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, bool
|
|||
FOutVector *v3d;
|
||||
polyvertex_t *pv;
|
||||
pslope_t *slope = NULL;
|
||||
INT32 shader = SHADER_DEFAULT;
|
||||
INT32 shader = SHADER_NONE;
|
||||
|
||||
size_t nrPlaneVerts;
|
||||
INT32 i;
|
||||
|
@ -652,7 +663,7 @@ static void HWR_AddTransparentWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, I
|
|||
//
|
||||
static void HWR_ProjectWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, FBITFIELD blendmode, INT32 lightlevel, extracolormap_t *wallcolormap)
|
||||
{
|
||||
INT32 shader = SHADER_DEFAULT;
|
||||
INT32 shader = SHADER_NONE;
|
||||
|
||||
HWR_Lighting(pSurf, lightlevel, wallcolormap);
|
||||
|
||||
|
@ -730,13 +741,15 @@ static void HWR_SplitWall(sector_t *sector, FOutVector *wallVerts, INT32 texnum,
|
|||
{
|
||||
if (pfloor && (pfloor->fofflags & FOF_FOG))
|
||||
{
|
||||
lightnum = HWR_CalcWallLight(pfloor->master->frontsector->lightlevel, v1x, v1y, v2x, v2y);
|
||||
lightnum = pfloor->master->frontsector->lightlevel;
|
||||
colormap = pfloor->master->frontsector->extra_colormap;
|
||||
lightnum = colormap ? lightnum : HWR_CalcWallLight(lightnum, v1x, v1y, v2x, v2y);
|
||||
}
|
||||
else
|
||||
{
|
||||
lightnum = HWR_CalcWallLight(*list[i].lightlevel, v1x, v1y, v2x, v2y);
|
||||
lightnum = *list[i].lightlevel;
|
||||
colormap = *list[i].extra_colormap;
|
||||
lightnum = colormap ? lightnum : HWR_CalcWallLight(lightnum, v1x, v1y, v2x, v2y);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -961,8 +974,9 @@ static void HWR_ProcessSeg(void)
|
|||
float cliplow = (float)texturehpeg;
|
||||
float cliphigh = (float)(texturehpeg + (gl_curline->flength*FRACUNIT));
|
||||
|
||||
FUINT lightnum = HWR_CalcWallLight(gl_frontsector->lightlevel, vs.x, vs.y, ve.x, ve.y);
|
||||
FUINT lightnum = gl_frontsector->lightlevel;
|
||||
extracolormap_t *colormap = gl_frontsector->extra_colormap;
|
||||
lightnum = colormap ? lightnum : HWR_CalcWallLight(lightnum, vs.x, vs.y, ve.x, ve.y);
|
||||
|
||||
FSurfaceInfo Surf;
|
||||
Surf.PolyColor.s.alpha = 255;
|
||||
|
@ -1557,8 +1571,9 @@ static void HWR_ProcessSeg(void)
|
|||
|
||||
blendmode = PF_Fog|PF_NoTexture;
|
||||
|
||||
lightnum = HWR_CalcWallLight(rover->master->frontsector->lightlevel, vs.x, vs.y, ve.x, ve.y);
|
||||
lightnum = rover->master->frontsector->lightlevel;
|
||||
colormap = rover->master->frontsector->extra_colormap;
|
||||
lightnum = colormap ? lightnum : HWR_CalcWallLight(lightnum, vs.x, vs.y, ve.x, ve.y);
|
||||
|
||||
Surf.PolyColor.s.alpha = HWR_FogBlockAlpha(rover->master->frontsector->lightlevel, rover->master->frontsector->extra_colormap);
|
||||
|
||||
|
@ -1679,8 +1694,9 @@ static void HWR_ProcessSeg(void)
|
|||
|
||||
blendmode = PF_Fog|PF_NoTexture;
|
||||
|
||||
lightnum = HWR_CalcWallLight(rover->master->frontsector->lightlevel, vs.x, vs.y, ve.x, ve.y);
|
||||
lightnum = rover->master->frontsector->lightlevel;
|
||||
colormap = rover->master->frontsector->extra_colormap;
|
||||
lightnum = colormap ? lightnum : HWR_CalcWallLight(lightnum, vs.x, vs.y, ve.x, ve.y);
|
||||
|
||||
Surf.PolyColor.s.alpha = HWR_FogBlockAlpha(rover->master->frontsector->lightlevel, rover->master->frontsector->extra_colormap);
|
||||
|
||||
|
@ -2007,7 +2023,7 @@ static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling,
|
|||
{
|
||||
FSurfaceInfo Surf;
|
||||
FOutVector *v3d;
|
||||
INT32 shader = SHADER_DEFAULT;
|
||||
INT32 shader = SHADER_NONE;
|
||||
|
||||
size_t nrPlaneVerts = polysector->numVertices;
|
||||
INT32 i;
|
||||
|
@ -2680,7 +2696,7 @@ static void HWR_DrawDropShadow(mobj_t *thing, fixed_t scale)
|
|||
float fscale; float fx; float fy; float offset;
|
||||
extracolormap_t *colormap = NULL;
|
||||
FBITFIELD blendmode = PF_Translucent|PF_Modulated;
|
||||
INT32 shader = SHADER_DEFAULT;
|
||||
INT32 shader = SHADER_NONE;
|
||||
UINT8 i;
|
||||
INT32 heightsec, phs;
|
||||
SINT8 flip = P_MobjFlip(thing);
|
||||
|
@ -2888,7 +2904,7 @@ static void HWR_SplitSprite(gl_vissprite_t *spr)
|
|||
boolean lightset = true;
|
||||
FBITFIELD blend = 0;
|
||||
FBITFIELD occlusion;
|
||||
INT32 shader = SHADER_DEFAULT;
|
||||
INT32 shader = SHADER_NONE;
|
||||
boolean use_linkdraw_hack = false;
|
||||
UINT8 alpha;
|
||||
|
||||
|
@ -3459,7 +3475,7 @@ static void HWR_DrawSprite(gl_vissprite_t *spr)
|
|||
}
|
||||
|
||||
{
|
||||
INT32 shader = SHADER_DEFAULT;
|
||||
INT32 shader = SHADER_NONE;
|
||||
FBITFIELD blend = 0;
|
||||
FBITFIELD occlusion;
|
||||
boolean use_linkdraw_hack = false;
|
||||
|
@ -3532,7 +3548,7 @@ static void HWR_DrawSprite(gl_vissprite_t *spr)
|
|||
// Sprite drawer for precipitation
|
||||
static inline void HWR_DrawPrecipitationSprite(gl_vissprite_t *spr)
|
||||
{
|
||||
INT32 shader = SHADER_DEFAULT;
|
||||
INT32 shader = SHADER_NONE;
|
||||
FBITFIELD blend = 0;
|
||||
FOutVector wallVerts[4];
|
||||
patch_t *gpatch;
|
||||
|
@ -3976,7 +3992,6 @@ static void HWR_CreateDrawNodes(void)
|
|||
|
||||
// Okay! Let's draw it all! Woo!
|
||||
HWD.pfnSetTransform(&atransform);
|
||||
HWD.pfnSetShader(SHADER_DEFAULT);
|
||||
|
||||
for (i = 0; i < p; i++)
|
||||
{
|
||||
|
@ -5003,7 +5018,8 @@ static void HWR_DrawSkyBackground(player_t *player)
|
|||
HWR_BuildSkyDome();
|
||||
}
|
||||
|
||||
HWD.pfnSetShader(SHADER_SKY); // sky shader
|
||||
if (HWR_UseShader())
|
||||
HWD.pfnSetShader(HWR_GetShaderFromTarget(SHADER_SKY));
|
||||
HWD.pfnSetTransform(&dometransform);
|
||||
HWD.pfnRenderSkyDome(&gl_sky);
|
||||
}
|
||||
|
@ -5089,8 +5105,6 @@ static void HWR_DrawSkyBackground(player_t *player)
|
|||
HWD.pfnUnSetShader();
|
||||
HWD.pfnDrawPolygon(NULL, v, 4, 0);
|
||||
}
|
||||
|
||||
HWD.pfnSetShader(SHADER_DEFAULT);
|
||||
}
|
||||
|
||||
|
||||
|
@ -5154,16 +5168,10 @@ static void HWR_SetTransformAiming(FTransform *trans, player_t *player, boolean
|
|||
//
|
||||
static void HWR_SetShaderState(void)
|
||||
{
|
||||
hwdshaderoption_t state = cv_glshaders.value;
|
||||
|
||||
if (!cv_glallowshaders.value)
|
||||
state = (cv_glshaders.value == HWD_SHADEROPTION_ON ? HWD_SHADEROPTION_NOCUSTOM : cv_glshaders.value);
|
||||
|
||||
HWD.pfnSetSpecialState(HWD_SET_SHADERS, (INT32)state);
|
||||
HWD.pfnSetShader(SHADER_DEFAULT);
|
||||
HWD.pfnSetSpecialState(HWD_SET_SHADERS, (INT32)HWR_UseShader());
|
||||
}
|
||||
|
||||
static void HWR_SetupView(player_t *player, float fpov, boolean skybox)
|
||||
static void HWR_SetupView(player_t *player, INT32 viewnumber, float fpov, boolean skybox)
|
||||
{
|
||||
postimg_t *type;
|
||||
|
||||
|
@ -5172,6 +5180,20 @@ static void HWR_SetupView(player_t *player, float fpov, boolean skybox)
|
|||
else
|
||||
type = &postimgtype;
|
||||
|
||||
if (!HWR_ShouldUsePaletteRendering())
|
||||
{
|
||||
// do we really need to save player (is it not the same)?
|
||||
player_t *saved_player = stplyr;
|
||||
stplyr = player;
|
||||
ST_doPaletteStuff();
|
||||
stplyr = saved_player;
|
||||
#ifdef ALAM_LIGHTING
|
||||
HWR_SetLights(viewnumber);
|
||||
#else
|
||||
(void)viewnumber;
|
||||
#endif
|
||||
}
|
||||
|
||||
// note: sets viewangle, viewx, viewy, viewz
|
||||
if (skybox)
|
||||
R_SkyboxFrame(player);
|
||||
|
@ -5228,20 +5250,7 @@ void HWR_RenderSkyboxView(INT32 viewnumber, player_t *player)
|
|||
{
|
||||
const float fpov = FixedToFloat(R_GetPlayerFov(player));
|
||||
|
||||
{
|
||||
// do we really need to save player (is it not the same)?
|
||||
player_t *saved_player = stplyr;
|
||||
stplyr = player;
|
||||
ST_doPaletteStuff();
|
||||
stplyr = saved_player;
|
||||
#ifdef ALAM_LIGHTING
|
||||
HWR_SetLights(viewnumber);
|
||||
#else
|
||||
(void)viewnumber;
|
||||
#endif
|
||||
}
|
||||
|
||||
HWR_SetupView(player, fpov, true);
|
||||
HWR_SetupView(player, viewnumber, fpov, true);
|
||||
|
||||
// check for new console commands.
|
||||
NetUpdate();
|
||||
|
@ -5353,18 +5362,7 @@ void HWR_RenderPlayerView(INT32 viewnumber, player_t *player)
|
|||
HWR_RenderSkyboxView(viewnumber, player); // This is drawn before everything else so it is placed behind
|
||||
PS_STOP_TIMING(ps_hw_skyboxtime);
|
||||
|
||||
{
|
||||
// do we really need to save player (is it not the same)?
|
||||
player_t *saved_player = stplyr;
|
||||
stplyr = player;
|
||||
ST_doPaletteStuff();
|
||||
stplyr = saved_player;
|
||||
#ifdef ALAM_LIGHTING
|
||||
HWR_SetLights(viewnumber);
|
||||
#endif
|
||||
}
|
||||
|
||||
HWR_SetupView(player, fpov, false);
|
||||
HWR_SetupView(player, viewnumber, fpov, false);
|
||||
|
||||
framecount++; // timedemo
|
||||
|
||||
|
@ -5467,6 +5465,56 @@ void HWR_RenderPlayerView(INT32 viewnumber, player_t *player)
|
|||
HWD.pfnGClipRect(0, 0, vid.width, vid.height, NZCLIP_PLANE);
|
||||
}
|
||||
|
||||
// Returns whether palette rendering is "actually enabled."
|
||||
// Can't have palette rendering if shaders are disabled.
|
||||
boolean HWR_ShouldUsePaletteRendering(void)
|
||||
{
|
||||
return (cv_glpaletterendering.value && HWR_UseShader());
|
||||
}
|
||||
|
||||
// enable or disable palette rendering state depending on settings and availability
|
||||
// called when relevant settings change
|
||||
// shader recompilation is done in the cvar callback
|
||||
static void HWR_TogglePaletteRendering(void)
|
||||
{
|
||||
// which state should we go to?
|
||||
if (HWR_ShouldUsePaletteRendering())
|
||||
{
|
||||
// are we not in that state already?
|
||||
if (!gl_palette_rendering_state)
|
||||
{
|
||||
gl_palette_rendering_state = true;
|
||||
|
||||
// The textures will still be converted to RGBA by r_opengl.
|
||||
// This however makes hw_cache use paletted blending for composite textures!
|
||||
// (patchformat is not touched)
|
||||
textureformat = GL_TEXFMT_P_8;
|
||||
|
||||
HWR_SetMapPalette();
|
||||
HWR_SetPalette(pLocalPalette);
|
||||
|
||||
// If the r_opengl "texture palette" stays the same during this switch, these textures
|
||||
// will not be cleared out. However they are still out of date since the
|
||||
// composite texture blending method has changed. Therefore they need to be cleared.
|
||||
HWR_LoadMapTextures(numtextures);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// are we not in that state already?
|
||||
if (gl_palette_rendering_state)
|
||||
{
|
||||
gl_palette_rendering_state = false;
|
||||
textureformat = GL_TEXFMT_RGBA;
|
||||
HWR_SetPalette(pLocalPalette);
|
||||
// If the r_opengl "texture palette" stays the same during this switch, these textures
|
||||
// will not be cleared out. However they are still out of date since the
|
||||
// composite texture blending method has changed. Therefore they need to be cleared.
|
||||
HWR_LoadMapTextures(numtextures);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HWR_LoadLevel(void)
|
||||
{
|
||||
#ifdef ALAM_LIGHTING
|
||||
|
@ -5480,6 +5528,9 @@ void HWR_LoadLevel(void)
|
|||
HWR_ClearSkyDome();
|
||||
HWR_BuildSkyDome();
|
||||
|
||||
if (HWR_ShouldUsePaletteRendering())
|
||||
HWR_SetMapPalette();
|
||||
|
||||
gl_maploaded = true;
|
||||
}
|
||||
|
||||
|
@ -5487,13 +5538,17 @@ void HWR_LoadLevel(void)
|
|||
// 3D ENGINE COMMANDS
|
||||
// ==========================================================================
|
||||
|
||||
static CV_PossibleValue_t glshaders_cons_t[] = {{HWD_SHADEROPTION_OFF, "Off"}, {HWD_SHADEROPTION_ON, "On"}, {HWD_SHADEROPTION_NOCUSTOM, "Ignore custom shaders"}, {0, NULL}};
|
||||
static CV_PossibleValue_t glshaders_cons_t[] = {{0, "Off"}, {1, "On"}, {2, "Ignore custom shaders"}, {0, NULL}};
|
||||
static CV_PossibleValue_t glmodelinterpolation_cons_t[] = {{0, "Off"}, {1, "Sometimes"}, {2, "Always"}, {0, NULL}};
|
||||
static CV_PossibleValue_t glfakecontrast_cons_t[] = {{0, "Off"}, {1, "On"}, {2, "Smooth"}, {0, NULL}};
|
||||
static CV_PossibleValue_t glshearing_cons_t[] = {{0, "Off"}, {1, "On"}, {2, "Third-person"}, {0, NULL}};
|
||||
|
||||
static void CV_glfiltermode_OnChange(void);
|
||||
static void CV_glanisotropic_OnChange(void);
|
||||
static void CV_glmodellighting_OnChange(void);
|
||||
static void CV_glpaletterendering_OnChange(void);
|
||||
static void CV_glpalettedepth_OnChange(void);
|
||||
static void CV_glshaders_OnChange(void);
|
||||
|
||||
static CV_PossibleValue_t glfiltermode_cons_t[]= {{HWD_SET_TEXTUREFILTER_POINTSAMPLED, "Nearest"},
|
||||
{HWD_SET_TEXTUREFILTER_BILINEAR, "Bilinear"}, {HWD_SET_TEXTUREFILTER_TRILINEAR, "Trilinear"},
|
||||
|
@ -5503,7 +5558,7 @@ static CV_PossibleValue_t glfiltermode_cons_t[]= {{HWD_SET_TEXTUREFILTER_POINTSA
|
|||
{0, NULL}};
|
||||
CV_PossibleValue_t glanisotropicmode_cons_t[] = {{1, "MIN"}, {16, "MAX"}, {0, NULL}};
|
||||
|
||||
consvar_t cv_glshaders = CVAR_INIT ("gr_shaders", "On", CV_SAVE, glshaders_cons_t, NULL);
|
||||
consvar_t cv_glshaders = CVAR_INIT ("gr_shaders", "On", CV_SAVE|CV_CALL, glshaders_cons_t, CV_glshaders_OnChange);
|
||||
|
||||
#ifdef ALAM_LIGHTING
|
||||
consvar_t cv_gldynamiclighting = CVAR_INIT ("gr_dynamiclighting", "On", CV_SAVE, CV_OnOff, NULL);
|
||||
|
@ -5514,7 +5569,7 @@ consvar_t cv_glcoronasize = CVAR_INIT ("gr_coronasize", "1", CV_SAVE|CV_FLOAT, 0
|
|||
|
||||
consvar_t cv_glmodels = CVAR_INIT ("gr_models", "Off", CV_SAVE, CV_OnOff, NULL);
|
||||
consvar_t cv_glmodelinterpolation = CVAR_INIT ("gr_modelinterpolation", "Sometimes", CV_SAVE, glmodelinterpolation_cons_t, NULL);
|
||||
consvar_t cv_glmodellighting = CVAR_INIT ("gr_modellighting", "Off", CV_SAVE, CV_OnOff, NULL);
|
||||
consvar_t cv_glmodellighting = CVAR_INIT ("gr_modellighting", "Off", CV_SAVE|CV_CALL, CV_OnOff, CV_glmodellighting_OnChange);
|
||||
|
||||
consvar_t cv_glshearing = CVAR_INIT ("gr_shearing", "Off", CV_SAVE, glshearing_cons_t, NULL);
|
||||
consvar_t cv_glspritebillboarding = CVAR_INIT ("gr_spritebillboarding", "Off", CV_SAVE, CV_OnOff, NULL);
|
||||
|
@ -5529,18 +5584,61 @@ consvar_t cv_glsolvetjoin = CVAR_INIT ("gr_solvetjoin", "On", 0, CV_OnOff, NULL)
|
|||
|
||||
consvar_t cv_glbatching = CVAR_INIT ("gr_batching", "On", 0, CV_OnOff, NULL);
|
||||
|
||||
static CV_PossibleValue_t glpalettedepth_cons_t[] = {{16, "16 bits"}, {24, "24 bits"}, {0, NULL}};
|
||||
|
||||
consvar_t cv_glpaletterendering = CVAR_INIT ("gr_paletterendering", "Off", CV_SAVE|CV_CALL, CV_OnOff, CV_glpaletterendering_OnChange);
|
||||
consvar_t cv_glpalettedepth = CVAR_INIT ("gr_palettedepth", "16 bits", CV_SAVE|CV_CALL, glpalettedepth_cons_t, CV_glpalettedepth_OnChange);
|
||||
|
||||
#define ONLY_IF_GL_LOADED if (vid.glstate != VID_GL_LIBRARY_LOADED) return;
|
||||
consvar_t cv_glwireframe = CVAR_INIT ("gr_wireframe", "Off", 0, CV_OnOff, NULL);
|
||||
|
||||
static void CV_glfiltermode_OnChange(void)
|
||||
{
|
||||
if (rendermode == render_opengl)
|
||||
HWD.pfnSetSpecialState(HWD_SET_TEXTUREFILTERMODE, cv_glfiltermode.value);
|
||||
ONLY_IF_GL_LOADED
|
||||
HWD.pfnSetSpecialState(HWD_SET_TEXTUREFILTERMODE, cv_glfiltermode.value);
|
||||
}
|
||||
|
||||
static void CV_glanisotropic_OnChange(void)
|
||||
{
|
||||
if (rendermode == render_opengl)
|
||||
HWD.pfnSetSpecialState(HWD_SET_TEXTUREANISOTROPICMODE, cv_glanisotropicmode.value);
|
||||
ONLY_IF_GL_LOADED
|
||||
HWD.pfnSetSpecialState(HWD_SET_TEXTUREANISOTROPICMODE, cv_glanisotropicmode.value);
|
||||
}
|
||||
|
||||
static void CV_glmodellighting_OnChange(void)
|
||||
{
|
||||
ONLY_IF_GL_LOADED
|
||||
// if shaders have been compiled, then they now need to be recompiled.
|
||||
if (gl_shadersavailable)
|
||||
HWR_CompileShaders();
|
||||
}
|
||||
|
||||
static void CV_glpaletterendering_OnChange(void)
|
||||
{
|
||||
ONLY_IF_GL_LOADED
|
||||
if (gl_shadersavailable)
|
||||
{
|
||||
HWR_CompileShaders();
|
||||
HWR_TogglePaletteRendering();
|
||||
}
|
||||
}
|
||||
|
||||
static void CV_glpalettedepth_OnChange(void)
|
||||
{
|
||||
ONLY_IF_GL_LOADED
|
||||
// refresh the screen palette
|
||||
if (HWR_ShouldUsePaletteRendering())
|
||||
HWR_SetPalette(pLocalPalette);
|
||||
}
|
||||
|
||||
static void CV_glshaders_OnChange(void)
|
||||
{
|
||||
ONLY_IF_GL_LOADED
|
||||
HWR_SetShaderState();
|
||||
if (cv_glpaletterendering.value)
|
||||
{
|
||||
// can't do palette rendering without shaders, so update the state if needed
|
||||
HWR_TogglePaletteRendering();
|
||||
}
|
||||
}
|
||||
|
||||
//added by Hurdler: console varibale that are saved
|
||||
|
@ -5569,6 +5667,8 @@ void HWR_AddCommands(void)
|
|||
|
||||
CV_RegisterVar(&cv_glbatching);
|
||||
|
||||
CV_RegisterVar(&cv_glpaletterendering);
|
||||
CV_RegisterVar(&cv_glpalettedepth);
|
||||
CV_RegisterVar(&cv_glwireframe);
|
||||
}
|
||||
|
||||
|
@ -5581,6 +5681,8 @@ void HWR_Startup(void)
|
|||
{
|
||||
CONS_Printf("HWR_Startup()...\n");
|
||||
|
||||
textureformat = patchformat = GL_TEXFMT_RGBA;
|
||||
|
||||
HWR_InitPolyPool();
|
||||
HWR_InitMapTextures();
|
||||
HWR_InitModels();
|
||||
|
@ -5588,14 +5690,12 @@ void HWR_Startup(void)
|
|||
HWR_InitLight();
|
||||
#endif
|
||||
|
||||
gl_shadersavailable = HWR_InitShaders();
|
||||
HWR_SetShaderState();
|
||||
HWR_LoadAllCustomShaders();
|
||||
if (!HWR_CompileShaders())
|
||||
gl_shadersavailable = false;
|
||||
HWR_TogglePaletteRendering();
|
||||
}
|
||||
|
||||
if (rendermode == render_opengl)
|
||||
textureformat = patchformat = GL_TEXFMT_RGBA;
|
||||
|
||||
gl_init = true;
|
||||
}
|
||||
|
||||
|
@ -5685,7 +5785,7 @@ void HWR_RenderWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, FBITFIELD blend,
|
|||
FBITFIELD blendmode = blend;
|
||||
UINT8 alpha = pSurf->PolyColor.s.alpha; // retain the alpha
|
||||
|
||||
INT32 shader = SHADER_DEFAULT;
|
||||
INT32 shader = SHADER_NONE;
|
||||
|
||||
// Lighting is done here instead so that fog isn't drawn incorrectly on transparent walls after sorting
|
||||
HWR_Lighting(pSurf, lightlevel, wallcolormap);
|
||||
|
@ -5730,7 +5830,7 @@ void HWR_DoPostProcessor(player_t *player)
|
|||
|
||||
// Armageddon Blast Flash!
|
||||
// Could this even be considered postprocessor?
|
||||
if (player->flashcount)
|
||||
if (player->flashcount && !HWR_ShouldUsePaletteRendering())
|
||||
{
|
||||
FOutVector v[4];
|
||||
FSurfaceInfo Surf;
|
||||
|
@ -5755,7 +5855,7 @@ void HWR_DoPostProcessor(player_t *player)
|
|||
|
||||
// Capture the screen for intermission and screen waving
|
||||
if(gamestate != GS_INTERMISSION)
|
||||
HWD.pfnMakeScreenTexture();
|
||||
HWD.pfnMakeScreenTexture(HWD_SCREENTEXTURE_GENERIC1);
|
||||
|
||||
if (splitscreen) // Not supported in splitscreen - someone want to add support?
|
||||
return;
|
||||
|
@ -5799,7 +5899,7 @@ void HWR_DoPostProcessor(player_t *player)
|
|||
|
||||
// Capture the screen again for screen waving on the intermission
|
||||
if(gamestate != GS_INTERMISSION)
|
||||
HWD.pfnMakeScreenTexture();
|
||||
HWD.pfnMakeScreenTexture(HWD_SCREENTEXTURE_GENERIC1);
|
||||
}
|
||||
// Flipping of the screen isn't done here anymore
|
||||
}
|
||||
|
@ -5807,18 +5907,18 @@ void HWR_DoPostProcessor(player_t *player)
|
|||
void HWR_StartScreenWipe(void)
|
||||
{
|
||||
//CONS_Debug(DBG_RENDER, "In HWR_StartScreenWipe()\n");
|
||||
HWD.pfnStartScreenWipe();
|
||||
HWD.pfnMakeScreenTexture(HWD_SCREENTEXTURE_WIPE_START);
|
||||
}
|
||||
|
||||
void HWR_EndScreenWipe(void)
|
||||
{
|
||||
//CONS_Debug(DBG_RENDER, "In HWR_EndScreenWipe()\n");
|
||||
HWD.pfnEndScreenWipe();
|
||||
HWD.pfnMakeScreenTexture(HWD_SCREENTEXTURE_WIPE_END);
|
||||
}
|
||||
|
||||
void HWR_DrawIntermissionBG(void)
|
||||
{
|
||||
HWD.pfnDrawIntermissionBG();
|
||||
HWD.pfnDrawScreenTexture(HWD_SCREENTEXTURE_GENERIC1, NULL, 0);
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -5863,201 +5963,40 @@ void HWR_DoWipe(UINT8 wipenum, UINT8 scrnnum)
|
|||
return;
|
||||
|
||||
HWR_GetFadeMask(wipelumpnum);
|
||||
HWD.pfnDoScreenWipe();
|
||||
}
|
||||
if (wipestyle == WIPESTYLE_COLORMAP && HWR_UseShader())
|
||||
{
|
||||
FSurfaceInfo surf = {0};
|
||||
FBITFIELD polyflags = PF_Modulated|PF_NoDepthTest;
|
||||
|
||||
void HWR_DoTintedWipe(UINT8 wipenum, UINT8 scrnnum)
|
||||
{
|
||||
// It does the same thing
|
||||
HWR_DoWipe(wipenum, scrnnum);
|
||||
polyflags |= (wipestyleflags & WSF_TOWHITE) ? PF_Additive : PF_ReverseSubtract;
|
||||
surf.PolyColor.s.red = FADEREDFACTOR;
|
||||
surf.PolyColor.s.green = FADEGREENFACTOR;
|
||||
surf.PolyColor.s.blue = FADEBLUEFACTOR;
|
||||
// polycolor alpha communicates fadein / fadeout to the shader and the backend
|
||||
surf.PolyColor.s.alpha = (wipestyleflags & WSF_FADEIN) ? 255 : 0;
|
||||
|
||||
HWD.pfnSetShader(HWR_GetShaderFromTarget(SHADER_UI_TINTED_WIPE));
|
||||
HWD.pfnDoScreenWipe(HWD_SCREENTEXTURE_WIPE_START, HWD_SCREENTEXTURE_WIPE_END,
|
||||
&surf, polyflags);
|
||||
HWD.pfnUnSetShader();
|
||||
}
|
||||
else
|
||||
{
|
||||
HWD.pfnDoScreenWipe(HWD_SCREENTEXTURE_WIPE_START, HWD_SCREENTEXTURE_WIPE_END,
|
||||
NULL, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void HWR_MakeScreenFinalTexture(void)
|
||||
{
|
||||
HWD.pfnMakeScreenFinalTexture();
|
||||
int tex = HWR_ShouldUsePaletteRendering() ? HWD_SCREENTEXTURE_GENERIC3 : HWD_SCREENTEXTURE_GENERIC2;
|
||||
HWD.pfnMakeScreenTexture(tex);
|
||||
}
|
||||
|
||||
void HWR_DrawScreenFinalTexture(int width, int height)
|
||||
{
|
||||
HWD.pfnDrawScreenFinalTexture(width, height);
|
||||
}
|
||||
|
||||
static inline UINT16 HWR_FindShaderDefs(UINT16 wadnum)
|
||||
{
|
||||
UINT16 i;
|
||||
lumpinfo_t *lump_p;
|
||||
|
||||
lump_p = wadfiles[wadnum]->lumpinfo;
|
||||
for (i = 0; i < wadfiles[wadnum]->numlumps; i++, lump_p++)
|
||||
if (memcmp(lump_p->name, "SHADERS", 7) == 0)
|
||||
return i;
|
||||
|
||||
return INT16_MAX;
|
||||
}
|
||||
|
||||
boolean HWR_CompileShaders(void)
|
||||
{
|
||||
return HWD.pfnCompileShaders();
|
||||
}
|
||||
|
||||
customshaderxlat_t shaderxlat[] =
|
||||
{
|
||||
{"Flat", SHADER_FLOOR},
|
||||
{"WallTexture", SHADER_WALL},
|
||||
{"Sprite", SHADER_SPRITE},
|
||||
{"Model", SHADER_MODEL},
|
||||
{"ModelLighting", SHADER_MODEL_LIGHTING},
|
||||
{"WaterRipple", SHADER_WATER},
|
||||
{"Fog", SHADER_FOG},
|
||||
{"Sky", SHADER_SKY},
|
||||
{NULL, 0},
|
||||
};
|
||||
|
||||
void HWR_LoadAllCustomShaders(void)
|
||||
{
|
||||
INT32 i;
|
||||
|
||||
// read every custom shader
|
||||
for (i = 0; i < numwadfiles; i++)
|
||||
HWR_LoadCustomShadersFromFile(i, W_FileHasFolders(wadfiles[i]));
|
||||
}
|
||||
|
||||
void HWR_LoadCustomShadersFromFile(UINT16 wadnum, boolean PK3)
|
||||
{
|
||||
UINT16 lump;
|
||||
char *shaderdef, *line;
|
||||
char *stoken;
|
||||
char *value;
|
||||
size_t size;
|
||||
int linenum = 1;
|
||||
int shadertype = 0;
|
||||
int i;
|
||||
|
||||
lump = HWR_FindShaderDefs(wadnum);
|
||||
if (lump == INT16_MAX)
|
||||
return;
|
||||
|
||||
shaderdef = W_CacheLumpNumPwad(wadnum, lump, PU_CACHE);
|
||||
size = W_LumpLengthPwad(wadnum, lump);
|
||||
|
||||
line = Z_Malloc(size+1, PU_STATIC, NULL);
|
||||
M_Memcpy(line, shaderdef, size);
|
||||
line[size] = '\0';
|
||||
|
||||
stoken = strtok(line, "\r\n ");
|
||||
while (stoken)
|
||||
{
|
||||
if ((stoken[0] == '/' && stoken[1] == '/')
|
||||
|| (stoken[0] == '#'))// skip comments
|
||||
{
|
||||
stoken = strtok(NULL, "\r\n");
|
||||
goto skip_field;
|
||||
}
|
||||
|
||||
if (!stricmp(stoken, "GLSL"))
|
||||
{
|
||||
value = strtok(NULL, "\r\n ");
|
||||
if (!value)
|
||||
{
|
||||
CONS_Alert(CONS_WARNING, "HWR_LoadCustomShadersFromFile: Missing shader type (file %s, line %d)\n", wadfiles[wadnum]->filename, linenum);
|
||||
stoken = strtok(NULL, "\r\n"); // skip end of line
|
||||
goto skip_lump;
|
||||
}
|
||||
|
||||
if (!stricmp(value, "VERTEX"))
|
||||
shadertype = 1;
|
||||
else if (!stricmp(value, "FRAGMENT"))
|
||||
shadertype = 2;
|
||||
|
||||
skip_lump:
|
||||
stoken = strtok(NULL, "\r\n ");
|
||||
linenum++;
|
||||
}
|
||||
else
|
||||
{
|
||||
value = strtok(NULL, "\r\n= ");
|
||||
if (!value)
|
||||
{
|
||||
CONS_Alert(CONS_WARNING, "HWR_LoadCustomShadersFromFile: Missing shader target (file %s, line %d)\n", wadfiles[wadnum]->filename, linenum);
|
||||
stoken = strtok(NULL, "\r\n"); // skip end of line
|
||||
goto skip_field;
|
||||
}
|
||||
|
||||
if (!shadertype)
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, "HWR_LoadCustomShadersFromFile: Missing shader type (file %s, line %d)\n", wadfiles[wadnum]->filename, linenum);
|
||||
Z_Free(line);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; shaderxlat[i].type; i++)
|
||||
{
|
||||
if (!stricmp(shaderxlat[i].type, stoken))
|
||||
{
|
||||
size_t shader_size;
|
||||
char *shader_source;
|
||||
char *shader_lumpname;
|
||||
UINT16 shader_lumpnum;
|
||||
|
||||
if (PK3)
|
||||
{
|
||||
shader_lumpname = Z_Malloc(strlen(value) + 12, PU_STATIC, NULL);
|
||||
strcpy(shader_lumpname, "Shaders/sh_");
|
||||
strcat(shader_lumpname, value);
|
||||
shader_lumpnum = W_CheckNumForFullNamePK3(shader_lumpname, wadnum, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
shader_lumpname = Z_Malloc(strlen(value) + 4, PU_STATIC, NULL);
|
||||
strcpy(shader_lumpname, "SH_");
|
||||
strcat(shader_lumpname, value);
|
||||
shader_lumpnum = W_CheckNumForNamePwad(shader_lumpname, wadnum, 0);
|
||||
}
|
||||
|
||||
if (shader_lumpnum == INT16_MAX)
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, "HWR_LoadCustomShadersFromFile: Missing shader source %s (file %s, line %d)\n", shader_lumpname, wadfiles[wadnum]->filename, linenum);
|
||||
Z_Free(shader_lumpname);
|
||||
continue;
|
||||
}
|
||||
|
||||
shader_size = W_LumpLengthPwad(wadnum, shader_lumpnum);
|
||||
shader_source = Z_Malloc(shader_size, PU_STATIC, NULL);
|
||||
W_ReadLumpPwad(wadnum, shader_lumpnum, shader_source);
|
||||
|
||||
HWD.pfnLoadCustomShader(shaderxlat[i].id, shader_source, shader_size, (shadertype == 2));
|
||||
|
||||
Z_Free(shader_source);
|
||||
Z_Free(shader_lumpname);
|
||||
}
|
||||
}
|
||||
|
||||
skip_field:
|
||||
stoken = strtok(NULL, "\r\n= ");
|
||||
linenum++;
|
||||
}
|
||||
}
|
||||
|
||||
Z_Free(line);
|
||||
return;
|
||||
}
|
||||
|
||||
const char *HWR_GetShaderName(INT32 shader)
|
||||
{
|
||||
INT32 i;
|
||||
|
||||
if (shader)
|
||||
{
|
||||
for (i = 0; shaderxlat[i].type; i++)
|
||||
{
|
||||
if (shaderxlat[i].id == shader)
|
||||
return shaderxlat[i].type;
|
||||
}
|
||||
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
return "Default";
|
||||
int tex = HWR_ShouldUsePaletteRendering() ? HWD_SCREENTEXTURE_GENERIC3 : HWD_SCREENTEXTURE_GENERIC2;
|
||||
HWD.pfnDrawScreenFinalTexture(tex, width, height);
|
||||
}
|
||||
|
||||
#endif // HWRENDER
|
||||
|
|
|
@ -58,11 +58,11 @@ void HWR_StartScreenWipe(void);
|
|||
void HWR_EndScreenWipe(void);
|
||||
void HWR_DrawIntermissionBG(void);
|
||||
void HWR_DoWipe(UINT8 wipenum, UINT8 scrnnum);
|
||||
void HWR_DoTintedWipe(UINT8 wipenum, UINT8 scrnnum);
|
||||
void HWR_MakeScreenFinalTexture(void);
|
||||
void HWR_DrawScreenFinalTexture(int width, int height);
|
||||
|
||||
// This stuff is put here so models can use them
|
||||
boolean HWR_UseShader(void);
|
||||
void HWR_Lighting(FSurfaceInfo *Surface, INT32 light_level, extracolormap_t *colormap);
|
||||
UINT8 HWR_FogBlockAlpha(INT32 light, extracolormap_t *colormap); // Let's see if this can work
|
||||
|
||||
|
@ -71,13 +71,7 @@ FBITFIELD HWR_GetBlendModeFlag(INT32 style);
|
|||
FBITFIELD HWR_SurfaceBlend(INT32 style, INT32 transtablenum, FSurfaceInfo *pSurf);
|
||||
FBITFIELD HWR_TranstableToAlpha(INT32 transtablenum, FSurfaceInfo *pSurf);
|
||||
|
||||
boolean HWR_CompileShaders(void);
|
||||
|
||||
void HWR_LoadAllCustomShaders(void);
|
||||
void HWR_LoadCustomShadersFromFile(UINT16 wadnum, boolean PK3);
|
||||
const char *HWR_GetShaderName(INT32 shader);
|
||||
|
||||
extern customshaderxlat_t shaderxlat[];
|
||||
boolean HWR_ShouldUsePaletteRendering(void);
|
||||
|
||||
extern CV_PossibleValue_t glanisotropicmode_cons_t[];
|
||||
|
||||
|
@ -100,8 +94,9 @@ extern consvar_t cv_glspritebillboarding;
|
|||
extern consvar_t cv_glskydome;
|
||||
extern consvar_t cv_glfakecontrast;
|
||||
extern consvar_t cv_glslopecontrast;
|
||||
|
||||
extern consvar_t cv_glbatching;
|
||||
extern consvar_t cv_glpaletterendering;
|
||||
extern consvar_t cv_glpalettedepth;
|
||||
|
||||
extern consvar_t cv_glwireframe;
|
||||
|
||||
|
|
|
@ -390,8 +390,6 @@ static void md2_loadTexture(md2_t *model)
|
|||
if (!grPatch->mipmap->downloaded && !grPatch->mipmap->data)
|
||||
{
|
||||
int w = 0, h = 0;
|
||||
UINT32 size;
|
||||
RGBA_t *image;
|
||||
|
||||
#ifdef HAVE_PNG
|
||||
grPatch->mipmap->format = PNG_Load(filename, &w, &h, grPatch);
|
||||
|
@ -412,13 +410,19 @@ static void md2_loadTexture(md2_t *model)
|
|||
grPatch->mipmap->width = (UINT16)w;
|
||||
grPatch->mipmap->height = (UINT16)h;
|
||||
|
||||
// Lactozilla: Apply colour cube
|
||||
image = grPatch->mipmap->data;
|
||||
size = w*h;
|
||||
while (size--)
|
||||
// for palette rendering, color cube is applied in post-processing instead of here
|
||||
if (!HWR_ShouldUsePaletteRendering())
|
||||
{
|
||||
V_CubeApply(&image->s.red, &image->s.green, &image->s.blue);
|
||||
image++;
|
||||
UINT32 size;
|
||||
RGBA_t *image;
|
||||
// Lactozilla: Apply colour cube
|
||||
image = grPatch->mipmap->data;
|
||||
size = w*h;
|
||||
while (size--)
|
||||
{
|
||||
V_CubeApply(&image->s.red, &image->s.green, &image->s.blue);
|
||||
image++;
|
||||
}
|
||||
}
|
||||
}
|
||||
HWD.pfnSetTexture(grPatch->mipmap);
|
||||
|
@ -1550,7 +1554,8 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
|
|||
p.flip = atransform.flip;
|
||||
p.mirror = atransform.mirror;
|
||||
|
||||
HWD.pfnSetShader(SHADER_MODEL); // model shader
|
||||
if (HWR_UseShader())
|
||||
HWD.pfnSetShader(HWR_GetShaderFromTarget(SHADER_MODEL));
|
||||
{
|
||||
float this_scale = FIXED_TO_FLOAT(interp.scale);
|
||||
|
||||
|
|
636
src/hardware/hw_shaders.c
Normal file
636
src/hardware/hw_shaders.c
Normal file
|
@ -0,0 +1,636 @@
|
|||
// SONIC ROBO BLAST 2
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2021 by Sonic Team Junior.
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
// See the 'LICENSE' file for more details.
|
||||
//-----------------------------------------------------------------------------
|
||||
/// \file hw_shaders.c
|
||||
/// \brief Handles the shaders used by the game.
|
||||
|
||||
#ifdef HWRENDER
|
||||
|
||||
#include "hw_glob.h"
|
||||
#include "hw_drv.h"
|
||||
#include "hw_shaders.h"
|
||||
#include "../z_zone.h"
|
||||
|
||||
// ================
|
||||
// Shader sources
|
||||
// ================
|
||||
|
||||
static struct {
|
||||
const char *vertex;
|
||||
const char *fragment;
|
||||
} const gl_shadersources[] = {
|
||||
// Floor shader
|
||||
{GLSL_DEFAULT_VERTEX_SHADER, GLSL_FLOOR_FRAGMENT_SHADER},
|
||||
|
||||
// Wall shader
|
||||
{GLSL_DEFAULT_VERTEX_SHADER, GLSL_WALL_FRAGMENT_SHADER},
|
||||
|
||||
// Sprite shader
|
||||
{GLSL_DEFAULT_VERTEX_SHADER, GLSL_WALL_FRAGMENT_SHADER},
|
||||
|
||||
// Model shader
|
||||
{GLSL_MODEL_VERTEX_SHADER, GLSL_MODEL_FRAGMENT_SHADER},
|
||||
|
||||
// Water shader
|
||||
{GLSL_DEFAULT_VERTEX_SHADER, GLSL_WATER_FRAGMENT_SHADER},
|
||||
|
||||
// Fog shader
|
||||
{GLSL_DEFAULT_VERTEX_SHADER, GLSL_FOG_FRAGMENT_SHADER},
|
||||
|
||||
// Sky shader
|
||||
{GLSL_DEFAULT_VERTEX_SHADER, GLSL_SKY_FRAGMENT_SHADER},
|
||||
|
||||
// Palette postprocess shader
|
||||
{GLSL_DEFAULT_VERTEX_SHADER, GLSL_PALETTE_POSTPROCESS_FRAGMENT_SHADER},
|
||||
|
||||
// UI colormap fade shader
|
||||
{GLSL_DEFAULT_VERTEX_SHADER, GLSL_UI_COLORMAP_FADE_FRAGMENT_SHADER},
|
||||
|
||||
// UI tinted wipe shader
|
||||
{GLSL_DEFAULT_VERTEX_SHADER, GLSL_UI_TINTED_WIPE_FRAGMENT_SHADER},
|
||||
|
||||
{NULL, NULL},
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int base_shader; // index of base shader_t
|
||||
int custom_shader; // index of custom shader_t
|
||||
} shadertarget_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char *vertex;
|
||||
char *fragment;
|
||||
boolean compiled;
|
||||
} shader_t; // these are in an array and accessed by indices
|
||||
|
||||
// the array has NUMSHADERTARGETS entries for base shaders and for custom shaders
|
||||
// the array could be expanded in the future to fit "dynamic" custom shaders that
|
||||
// aren't fixed to shader targets
|
||||
static shader_t gl_shaders[NUMSHADERTARGETS*2];
|
||||
|
||||
static shadertarget_t gl_shadertargets[NUMSHADERTARGETS];
|
||||
|
||||
#define WHITESPACE_CHARS " \t"
|
||||
|
||||
#define MODEL_LIGHTING_DEFINE "#define SRB2_MODEL_LIGHTING"
|
||||
#define PALETTE_RENDERING_DEFINE "#define SRB2_PALETTE_RENDERING"
|
||||
|
||||
// Initialize shader variables and the backend's shader system. Load the base shaders.
|
||||
// Returns false if shaders cannot be used.
|
||||
boolean HWR_InitShaders(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!HWD.pfnInitShaders())
|
||||
return false;
|
||||
|
||||
for (i = 0; i < NUMSHADERTARGETS; i++)
|
||||
{
|
||||
// set up string pointers for base shaders
|
||||
gl_shaders[i].vertex = Z_StrDup(gl_shadersources[i].vertex);
|
||||
gl_shaders[i].fragment = Z_StrDup(gl_shadersources[i].fragment);
|
||||
// set shader target indices to correct values
|
||||
gl_shadertargets[i].base_shader = i;
|
||||
gl_shadertargets[i].custom_shader = -1;
|
||||
}
|
||||
|
||||
HWR_CompileShaders();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// helper function: strstr but returns an int with the substring position
|
||||
// returns INT32_MAX if not found
|
||||
static INT32 strstr_int(const char *str1, const char *str2)
|
||||
{
|
||||
char *location = strstr(str1, str2);
|
||||
if (location)
|
||||
return location - str1;
|
||||
else
|
||||
return INT32_MAX;
|
||||
}
|
||||
|
||||
// Creates a preprocessed copy of the shader according to the current graphics settings
|
||||
// Returns a pointer to the results on success and NULL on failure.
|
||||
// Remember memory management of the returned string.
|
||||
static char *HWR_PreprocessShader(char *original)
|
||||
{
|
||||
const char *line_ending = "\n";
|
||||
int line_ending_len;
|
||||
char *read_pos = original;
|
||||
int original_len = strlen(original);
|
||||
int distance_to_end = original_len;
|
||||
int new_len;
|
||||
char *new_shader;
|
||||
char *write_pos;
|
||||
char shader_glsl_version[3];
|
||||
int version_pos = -1;
|
||||
int version_len = 0;
|
||||
|
||||
if (strstr(original, "\r\n"))
|
||||
{
|
||||
line_ending = "\r\n";
|
||||
// check if all line endings are same
|
||||
while ((read_pos = strchr(read_pos, '\n')))
|
||||
{
|
||||
read_pos--;
|
||||
if (*read_pos != '\r')
|
||||
{
|
||||
// this file contains mixed CRLF and LF line endings.
|
||||
// treating it as a LF file during parsing should keep
|
||||
// the results sane enough as long as the gpu driver is fine
|
||||
// with these kinds of weirdly formatted shader sources.
|
||||
line_ending = "\n";
|
||||
break;
|
||||
}
|
||||
read_pos += 2;
|
||||
}
|
||||
read_pos = original;
|
||||
}
|
||||
|
||||
line_ending_len = strlen(line_ending);
|
||||
|
||||
// Find the #version directive, if it exists. Also don't get fooled if it's
|
||||
// inside a comment. Copy the version digits so they can be used in the preamble.
|
||||
// Time for some string parsing :D
|
||||
|
||||
#define STARTSWITH(str, with_what) !strncmp(str, with_what, sizeof(with_what)-1)
|
||||
#define ADVANCE(amount) read_pos += (amount); distance_to_end -= (amount);
|
||||
while (true)
|
||||
{
|
||||
// we're at the start of a line or at the end of a block comment.
|
||||
// first get any possible whitespace out of the way
|
||||
int whitespace_len = strspn(read_pos, WHITESPACE_CHARS);
|
||||
if (whitespace_len == distance_to_end)
|
||||
break; // we got to the end
|
||||
ADVANCE(whitespace_len)
|
||||
|
||||
if (STARTSWITH(read_pos, "#version"))
|
||||
{
|
||||
// found a version directive (and it's not inside a comment)
|
||||
// now locate, verify and read the version number
|
||||
int version_number_len;
|
||||
version_pos = read_pos - original;
|
||||
ADVANCE(sizeof("#version") - 1)
|
||||
whitespace_len = strspn(read_pos, WHITESPACE_CHARS);
|
||||
if (!whitespace_len)
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, "HWR_PreprocessShader: Syntax error in #version. Expected space after #version, but got other text.\n");
|
||||
return NULL;
|
||||
}
|
||||
else if (whitespace_len == distance_to_end)
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, "HWR_PreprocessShader: Syntax error in #version. Expected version number, but got end of file.\n");
|
||||
return NULL;
|
||||
}
|
||||
ADVANCE(whitespace_len)
|
||||
version_number_len = strspn(read_pos, "0123456789");
|
||||
if (!version_number_len)
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, "HWR_PreprocessShader: Syntax error in #version. Expected version number, but got other text.\n");
|
||||
return NULL;
|
||||
}
|
||||
else if (version_number_len != 3)
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, "HWR_PreprocessShader: Syntax error in #version. Expected version with 3 digits, but got %d digits.\n", version_number_len);
|
||||
return NULL;
|
||||
}
|
||||
M_Memcpy(shader_glsl_version, read_pos, 3);
|
||||
ADVANCE(version_number_len)
|
||||
version_len = (read_pos - original) - version_pos;
|
||||
whitespace_len = strspn(read_pos, WHITESPACE_CHARS);
|
||||
ADVANCE(whitespace_len)
|
||||
if (STARTSWITH(read_pos, "es"))
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, "HWR_PreprocessShader: Support for ES shaders is not implemented.\n");
|
||||
return NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
// go to next newline or end of next block comment if it starts before the newline
|
||||
// and is not inside a line comment
|
||||
INT32 newline_pos = strstr_int(read_pos, line_ending);
|
||||
INT32 line_comment_pos;
|
||||
INT32 block_comment_pos;
|
||||
// optimization: temporarily put a null at the line ending, so strstr does not needlessly
|
||||
// look past it since we're only interested in the current line
|
||||
if (newline_pos != INT32_MAX)
|
||||
read_pos[newline_pos] = '\0';
|
||||
line_comment_pos = strstr_int(read_pos, "//");
|
||||
block_comment_pos = strstr_int(read_pos, "/*");
|
||||
// restore the line ending, remove the null we just put there
|
||||
if (newline_pos != INT32_MAX)
|
||||
read_pos[newline_pos] = line_ending[0];
|
||||
if (line_comment_pos < block_comment_pos)
|
||||
{
|
||||
// line comment found, skip rest of the line
|
||||
if (newline_pos != INT32_MAX)
|
||||
{
|
||||
ADVANCE(newline_pos + line_ending_len)
|
||||
}
|
||||
else
|
||||
{
|
||||
// we got to the end
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (block_comment_pos < line_comment_pos)
|
||||
{
|
||||
// block comment found, skip past it
|
||||
INT32 block_comment_end;
|
||||
ADVANCE(block_comment_pos + 2)
|
||||
block_comment_end = strstr_int(read_pos, "*/");
|
||||
if (block_comment_end == INT32_MAX)
|
||||
{
|
||||
// could also leave insertion_pos at 0 and let the GLSL compiler
|
||||
// output an error message for this broken comment
|
||||
CONS_Alert(CONS_ERROR, "HWR_PreprocessShader: Encountered unclosed block comment in shader.\n");
|
||||
return NULL;
|
||||
}
|
||||
ADVANCE(block_comment_end + 2)
|
||||
}
|
||||
else if (newline_pos == INT32_MAX)
|
||||
{
|
||||
// we got to the end
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
// nothing special on this line, move to the next one
|
||||
ADVANCE(newline_pos + line_ending_len)
|
||||
}
|
||||
}
|
||||
}
|
||||
#undef STARTSWITH
|
||||
#undef ADVANCE
|
||||
|
||||
#define ADD_TO_LEN(def) new_len += sizeof(def) - 1 + line_ending_len;
|
||||
|
||||
// Calculate length of modified shader.
|
||||
new_len = original_len;
|
||||
if (cv_glmodellighting.value)
|
||||
ADD_TO_LEN(MODEL_LIGHTING_DEFINE)
|
||||
if (cv_glpaletterendering.value)
|
||||
ADD_TO_LEN(PALETTE_RENDERING_DEFINE)
|
||||
|
||||
#undef ADD_TO_LEN
|
||||
|
||||
#define VERSION_PART "#version "
|
||||
|
||||
if (new_len != original_len)
|
||||
{
|
||||
if (version_pos != -1)
|
||||
new_len += sizeof(VERSION_PART) - 1 + 3 + line_ending_len;
|
||||
new_len += sizeof("#line 0") - 1 + line_ending_len;
|
||||
}
|
||||
|
||||
// Allocate memory for modified shader.
|
||||
new_shader = Z_Malloc(new_len + 1, PU_STATIC, NULL);
|
||||
|
||||
read_pos = original;
|
||||
write_pos = new_shader;
|
||||
|
||||
if (new_len != original_len && version_pos != -1)
|
||||
{
|
||||
strcpy(write_pos, VERSION_PART);
|
||||
write_pos += sizeof(VERSION_PART) - 1;
|
||||
M_Memcpy(write_pos, shader_glsl_version, 3);
|
||||
write_pos += 3;
|
||||
strcpy(write_pos, line_ending);
|
||||
write_pos += line_ending_len;
|
||||
}
|
||||
|
||||
#undef VERSION_PART
|
||||
|
||||
#define WRITE_DEFINE(define) \
|
||||
{ \
|
||||
strcpy(write_pos, define); \
|
||||
write_pos += sizeof(define) - 1; \
|
||||
strcpy(write_pos, line_ending); \
|
||||
write_pos += line_ending_len; \
|
||||
}
|
||||
|
||||
// Write the defines.
|
||||
if (cv_glmodellighting.value)
|
||||
WRITE_DEFINE(MODEL_LIGHTING_DEFINE)
|
||||
if (cv_glpaletterendering.value)
|
||||
WRITE_DEFINE(PALETTE_RENDERING_DEFINE)
|
||||
|
||||
#undef WRITE_DEFINE
|
||||
|
||||
// Write a #line directive, so compiler errors will report line numbers from the
|
||||
// original shader without our preamble lines.
|
||||
if (new_len != original_len)
|
||||
{
|
||||
// line numbering in the #line directive is different for versions 110-150
|
||||
if (version_pos == -1 || shader_glsl_version[0] == '1')
|
||||
strcpy(write_pos, "#line 0");
|
||||
else
|
||||
strcpy(write_pos, "#line 1");
|
||||
write_pos += sizeof("#line 0") - 1;
|
||||
strcpy(write_pos, line_ending);
|
||||
write_pos += line_ending_len;
|
||||
}
|
||||
|
||||
// Copy the original shader.
|
||||
M_Memcpy(write_pos, read_pos, original_len);
|
||||
|
||||
// Erase the original #version directive, if it exists and was copied.
|
||||
if (new_len != original_len && version_pos != -1)
|
||||
memset(write_pos + version_pos, ' ', version_len);
|
||||
|
||||
// Terminate the new string.
|
||||
new_shader[new_len] = '\0';
|
||||
|
||||
return new_shader;
|
||||
}
|
||||
|
||||
// preprocess and compile shader at gl_shaders[index]
|
||||
static void HWR_CompileShader(int index)
|
||||
{
|
||||
char *vertex_source = gl_shaders[index].vertex;
|
||||
char *fragment_source = gl_shaders[index].fragment;
|
||||
|
||||
if (vertex_source)
|
||||
{
|
||||
char *preprocessed = HWR_PreprocessShader(vertex_source);
|
||||
if (!preprocessed) return;
|
||||
HWD.pfnLoadShader(index, preprocessed, HWD_SHADERSTAGE_VERTEX);
|
||||
}
|
||||
if (fragment_source)
|
||||
{
|
||||
char *preprocessed = HWR_PreprocessShader(fragment_source);
|
||||
if (!preprocessed) return;
|
||||
HWD.pfnLoadShader(index, preprocessed, HWD_SHADERSTAGE_FRAGMENT);
|
||||
}
|
||||
|
||||
gl_shaders[index].compiled = HWD.pfnCompileShader(index);
|
||||
}
|
||||
|
||||
// compile or recompile shaders
|
||||
void HWR_CompileShaders(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NUMSHADERTARGETS; i++)
|
||||
{
|
||||
int custom_index = gl_shadertargets[i].custom_shader;
|
||||
HWR_CompileShader(i);
|
||||
if (!gl_shaders[i].compiled)
|
||||
CONS_Alert(CONS_ERROR, "HWR_CompileShaders: Compilation failed for base %s shader!\n", shaderxlat[i].type);
|
||||
if (custom_index != -1)
|
||||
{
|
||||
HWR_CompileShader(custom_index);
|
||||
if (!gl_shaders[custom_index].compiled)
|
||||
CONS_Alert(CONS_ERROR, "HWR_CompileShaders: Recompilation failed for the custom %s shader! See the console messages above for more information.\n", shaderxlat[i].type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int HWR_GetShaderFromTarget(int shader_target)
|
||||
{
|
||||
int custom_shader = gl_shadertargets[shader_target].custom_shader;
|
||||
// use custom shader if following are true
|
||||
// - custom shader exists
|
||||
// - custom shader has been compiled successfully
|
||||
// - custom shaders are enabled
|
||||
// - custom shaders are allowed by the server
|
||||
if (custom_shader != -1 && gl_shaders[custom_shader].compiled &&
|
||||
cv_glshaders.value == 1 && cv_glallowshaders.value)
|
||||
return custom_shader;
|
||||
else
|
||||
return gl_shadertargets[shader_target].base_shader;
|
||||
}
|
||||
|
||||
static inline UINT16 HWR_FindShaderDefs(UINT16 wadnum)
|
||||
{
|
||||
UINT16 i;
|
||||
lumpinfo_t *lump_p;
|
||||
|
||||
lump_p = wadfiles[wadnum]->lumpinfo;
|
||||
for (i = 0; i < wadfiles[wadnum]->numlumps; i++, lump_p++)
|
||||
if (memcmp(lump_p->name, "SHADERS", 7) == 0)
|
||||
return i;
|
||||
|
||||
return INT16_MAX;
|
||||
}
|
||||
|
||||
customshaderxlat_t shaderxlat[] =
|
||||
{
|
||||
{"Flat", SHADER_FLOOR},
|
||||
{"WallTexture", SHADER_WALL},
|
||||
{"Sprite", SHADER_SPRITE},
|
||||
{"Model", SHADER_MODEL},
|
||||
{"WaterRipple", SHADER_WATER},
|
||||
{"Fog", SHADER_FOG},
|
||||
{"Sky", SHADER_SKY},
|
||||
{"PalettePostprocess", SHADER_PALETTE_POSTPROCESS},
|
||||
{"UIColormapFade", SHADER_UI_COLORMAP_FADE},
|
||||
{"UITintedWipe", SHADER_UI_TINTED_WIPE},
|
||||
{NULL, 0},
|
||||
};
|
||||
|
||||
void HWR_LoadAllCustomShaders(void)
|
||||
{
|
||||
INT32 i;
|
||||
|
||||
// read every custom shader
|
||||
for (i = 0; i < numwadfiles; i++)
|
||||
HWR_LoadCustomShadersFromFile(i, W_FileHasFolders(wadfiles[i]));
|
||||
}
|
||||
|
||||
void HWR_LoadCustomShadersFromFile(UINT16 wadnum, boolean PK3)
|
||||
{
|
||||
UINT16 lump;
|
||||
char *shaderdef, *line;
|
||||
char *stoken;
|
||||
char *value;
|
||||
size_t size;
|
||||
int linenum = 1;
|
||||
int shadertype = 0;
|
||||
int i;
|
||||
boolean modified_shaders[NUMSHADERTARGETS] = {0};
|
||||
|
||||
if (!gl_shadersavailable)
|
||||
return;
|
||||
|
||||
lump = HWR_FindShaderDefs(wadnum);
|
||||
if (lump == INT16_MAX)
|
||||
return;
|
||||
|
||||
shaderdef = W_CacheLumpNumPwad(wadnum, lump, PU_CACHE);
|
||||
size = W_LumpLengthPwad(wadnum, lump);
|
||||
|
||||
line = Z_Malloc(size+1, PU_STATIC, NULL);
|
||||
M_Memcpy(line, shaderdef, size);
|
||||
line[size] = '\0';
|
||||
|
||||
stoken = strtok(line, "\r\n ");
|
||||
while (stoken)
|
||||
{
|
||||
if ((stoken[0] == '/' && stoken[1] == '/')
|
||||
|| (stoken[0] == '#'))// skip comments
|
||||
{
|
||||
stoken = strtok(NULL, "\r\n");
|
||||
goto skip_field;
|
||||
}
|
||||
|
||||
if (!stricmp(stoken, "GLSL"))
|
||||
{
|
||||
value = strtok(NULL, "\r\n ");
|
||||
if (!value)
|
||||
{
|
||||
CONS_Alert(CONS_WARNING, "HWR_LoadCustomShadersFromFile: Missing shader type (file %s, line %d)\n", wadfiles[wadnum]->filename, linenum);
|
||||
stoken = strtok(NULL, "\r\n"); // skip end of line
|
||||
goto skip_lump;
|
||||
}
|
||||
|
||||
if (!stricmp(value, "VERTEX"))
|
||||
shadertype = 1;
|
||||
else if (!stricmp(value, "FRAGMENT"))
|
||||
shadertype = 2;
|
||||
|
||||
skip_lump:
|
||||
stoken = strtok(NULL, "\r\n ");
|
||||
linenum++;
|
||||
}
|
||||
else
|
||||
{
|
||||
value = strtok(NULL, "\r\n= ");
|
||||
if (!value)
|
||||
{
|
||||
CONS_Alert(CONS_WARNING, "HWR_LoadCustomShadersFromFile: Missing shader target (file %s, line %d)\n", wadfiles[wadnum]->filename, linenum);
|
||||
stoken = strtok(NULL, "\r\n"); // skip end of line
|
||||
goto skip_field;
|
||||
}
|
||||
|
||||
if (!shadertype)
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, "HWR_LoadCustomShadersFromFile: Missing shader type (file %s, line %d)\n", wadfiles[wadnum]->filename, linenum);
|
||||
Z_Free(line);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; shaderxlat[i].type; i++)
|
||||
{
|
||||
if (!stricmp(shaderxlat[i].type, stoken))
|
||||
{
|
||||
size_t shader_string_length;
|
||||
char *shader_source;
|
||||
char *shader_lumpname;
|
||||
UINT16 shader_lumpnum;
|
||||
int shader_index; // index in gl_shaders
|
||||
|
||||
if (PK3)
|
||||
{
|
||||
shader_lumpname = Z_Malloc(strlen(value) + 12, PU_STATIC, NULL);
|
||||
strcpy(shader_lumpname, "Shaders/sh_");
|
||||
strcat(shader_lumpname, value);
|
||||
shader_lumpnum = W_CheckNumForFullNamePK3(shader_lumpname, wadnum, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
shader_lumpname = Z_Malloc(strlen(value) + 4, PU_STATIC, NULL);
|
||||
strcpy(shader_lumpname, "SH_");
|
||||
strcat(shader_lumpname, value);
|
||||
shader_lumpnum = W_CheckNumForNamePwad(shader_lumpname, wadnum, 0);
|
||||
}
|
||||
|
||||
if (shader_lumpnum == INT16_MAX)
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, "HWR_LoadCustomShadersFromFile: Missing shader source %s (file %s, line %d)\n", shader_lumpname, wadfiles[wadnum]->filename, linenum);
|
||||
Z_Free(shader_lumpname);
|
||||
continue;
|
||||
}
|
||||
|
||||
shader_string_length = W_LumpLengthPwad(wadnum, shader_lumpnum) + 1;
|
||||
shader_source = Z_Malloc(shader_string_length, PU_STATIC, NULL);
|
||||
W_ReadLumpPwad(wadnum, shader_lumpnum, shader_source);
|
||||
shader_source[shader_string_length-1] = '\0';
|
||||
|
||||
shader_index = shaderxlat[i].id + NUMSHADERTARGETS;
|
||||
if (!modified_shaders[shaderxlat[i].id])
|
||||
{
|
||||
// this will clear any old custom shaders from previously loaded files
|
||||
// Z_Free checks if the pointer is NULL!
|
||||
Z_Free(gl_shaders[shader_index].vertex);
|
||||
gl_shaders[shader_index].vertex = NULL;
|
||||
Z_Free(gl_shaders[shader_index].fragment);
|
||||
gl_shaders[shader_index].fragment = NULL;
|
||||
}
|
||||
modified_shaders[shaderxlat[i].id] = true;
|
||||
|
||||
if (shadertype == 1)
|
||||
{
|
||||
if (gl_shaders[shader_index].vertex)
|
||||
{
|
||||
CONS_Alert(CONS_WARNING, "HWR_LoadCustomShadersFromFile: %s is overwriting another %s vertex shader from the same addon! (file %s, line %d)\n", shader_lumpname, shaderxlat[i].type, wadfiles[wadnum]->filename, linenum);
|
||||
Z_Free(gl_shaders[shader_index].vertex);
|
||||
}
|
||||
gl_shaders[shader_index].vertex = shader_source;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (gl_shaders[shader_index].fragment)
|
||||
{
|
||||
CONS_Alert(CONS_WARNING, "HWR_LoadCustomShadersFromFile: %s is overwriting another %s fragment shader from the same addon! (file %s, line %d)\n", shader_lumpname, shaderxlat[i].type, wadfiles[wadnum]->filename, linenum);
|
||||
Z_Free(gl_shaders[shader_index].fragment);
|
||||
}
|
||||
gl_shaders[shader_index].fragment = shader_source;
|
||||
}
|
||||
|
||||
Z_Free(shader_lumpname);
|
||||
}
|
||||
}
|
||||
|
||||
skip_field:
|
||||
stoken = strtok(NULL, "\r\n= ");
|
||||
linenum++;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < NUMSHADERTARGETS; i++)
|
||||
{
|
||||
if (modified_shaders[i])
|
||||
{
|
||||
int shader_index = i + NUMSHADERTARGETS; // index to gl_shaders
|
||||
gl_shadertargets[i].custom_shader = shader_index;
|
||||
// if only one stage (vertex/fragment) is defined, the other one
|
||||
// is copied from the base shaders.
|
||||
if (!gl_shaders[shader_index].fragment)
|
||||
gl_shaders[shader_index].fragment = Z_StrDup(gl_shadersources[i].fragment);
|
||||
if (!gl_shaders[shader_index].vertex)
|
||||
gl_shaders[shader_index].vertex = Z_StrDup(gl_shadersources[i].vertex);
|
||||
HWR_CompileShader(shader_index);
|
||||
if (!gl_shaders[shader_index].compiled)
|
||||
CONS_Alert(CONS_ERROR, "HWR_LoadCustomShadersFromFile: A compilation error occured for the %s shader in file %s. See the console messages above for more information.\n", shaderxlat[i].type, wadfiles[wadnum]->filename);
|
||||
}
|
||||
}
|
||||
|
||||
Z_Free(line);
|
||||
return;
|
||||
}
|
||||
|
||||
const char *HWR_GetShaderName(INT32 shader)
|
||||
{
|
||||
INT32 i;
|
||||
|
||||
for (i = 0; shaderxlat[i].type; i++)
|
||||
{
|
||||
if (shaderxlat[i].id == shader)
|
||||
return shaderxlat[i].type;
|
||||
}
|
||||
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
#endif // HWRENDER
|
424
src/hardware/hw_shaders.h
Normal file
424
src/hardware/hw_shaders.h
Normal file
|
@ -0,0 +1,424 @@
|
|||
// SONIC ROBO BLAST 2
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2021 by Sonic Team Junior.
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
// See the 'LICENSE' file for more details.
|
||||
//-----------------------------------------------------------------------------
|
||||
/// \file hw_shaders.h
|
||||
/// \brief Handles the shaders used by the game.
|
||||
|
||||
#ifndef _HW_SHADERS_H_
|
||||
#define _HW_SHADERS_H_
|
||||
|
||||
#include "../doomtype.h"
|
||||
|
||||
// ================
|
||||
// Vertex shaders
|
||||
// ================
|
||||
|
||||
//
|
||||
// Generic vertex shader
|
||||
//
|
||||
|
||||
#define GLSL_DEFAULT_VERTEX_SHADER \
|
||||
"void main()\n" \
|
||||
"{\n" \
|
||||
"gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex;\n" \
|
||||
"gl_FrontColor = gl_Color;\n" \
|
||||
"gl_TexCoord[0].xy = gl_MultiTexCoord0.xy;\n" \
|
||||
"gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;\n" \
|
||||
"}\0"
|
||||
|
||||
// replicates the way fixed function lighting is used by the model lighting option,
|
||||
// stores the lighting result to gl_Color
|
||||
// (ambient lighting of 0.75 and diffuse lighting from above)
|
||||
#define GLSL_MODEL_VERTEX_SHADER \
|
||||
"void main()\n" \
|
||||
"{\n" \
|
||||
"#ifdef SRB2_MODEL_LIGHTING\n" \
|
||||
"float nDotVP = dot(gl_Normal, vec3(0, 1, 0));\n" \
|
||||
"float light = min(0.75 + max(nDotVP, 0.0), 1.0);\n" \
|
||||
"gl_FrontColor = vec4(light, light, light, 1.0);\n" \
|
||||
"#else\n" \
|
||||
"gl_FrontColor = gl_Color;\n" \
|
||||
"#endif\n" \
|
||||
"gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex;\n" \
|
||||
"gl_TexCoord[0].xy = gl_MultiTexCoord0.xy;\n" \
|
||||
"gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;\n" \
|
||||
"}\0"
|
||||
|
||||
// ==================
|
||||
// Fragment shaders
|
||||
// ==================
|
||||
|
||||
//
|
||||
// Generic fragment shader
|
||||
//
|
||||
|
||||
#define GLSL_DEFAULT_FRAGMENT_SHADER \
|
||||
"uniform sampler2D tex;\n" \
|
||||
"uniform vec4 poly_color;\n" \
|
||||
"void main(void) {\n" \
|
||||
"gl_FragColor = texture2D(tex, gl_TexCoord[0].st) * poly_color;\n" \
|
||||
"}\0"
|
||||
|
||||
//
|
||||
// Software fragment shader
|
||||
//
|
||||
|
||||
// Include GLSL_FLOOR_FUDGES or GLSL_WALL_FUDGES or define the fudges in shaders that use this macro.
|
||||
#define GLSL_DOOM_COLORMAP \
|
||||
"float R_DoomColormap(float light, float z)\n" \
|
||||
"{\n" \
|
||||
"float lightnum = clamp(light / 17.0, 0.0, 15.0);\n" \
|
||||
"float lightz = clamp(z / 16.0, 0.0, 127.0);\n" \
|
||||
"float startmap = (15.0 - lightnum) * 4.0;\n" \
|
||||
"float scale = 160.0 / (lightz + 1.0);\n" \
|
||||
"float cap = (155.0 - light) * 0.26;\n" \
|
||||
"return max(startmap * STARTMAP_FUDGE - scale * 0.5 * SCALE_FUDGE, cap);\n" \
|
||||
"}\n"
|
||||
// lighting cap adjustment:
|
||||
// first num (155.0), increase to make it start to go dark sooner
|
||||
// second num (0.26), increase to make it go dark faster
|
||||
|
||||
#define GLSL_DOOM_LIGHT_EQUATION \
|
||||
"float R_DoomLightingEquation(float light)\n" \
|
||||
"{\n" \
|
||||
"float z = gl_FragCoord.z / gl_FragCoord.w;\n" \
|
||||
"float colormap = floor(R_DoomColormap(light, z)) + 0.5;\n" \
|
||||
"return clamp(colormap, 0.0, 31.0) / 32.0;\n" \
|
||||
"}\n"
|
||||
|
||||
#define GLSL_SOFTWARE_TINT_EQUATION \
|
||||
"if (tint_color.a > 0.0) {\n" \
|
||||
"float color_bright = sqrt((base_color.r * base_color.r) + (base_color.g * base_color.g) + (base_color.b * base_color.b));\n" \
|
||||
"float strength = sqrt(9.0 * tint_color.a);\n" \
|
||||
"final_color.r = clamp((color_bright * (tint_color.r * strength)) + (base_color.r * (1.0 - strength)), 0.0, 1.0);\n" \
|
||||
"final_color.g = clamp((color_bright * (tint_color.g * strength)) + (base_color.g * (1.0 - strength)), 0.0, 1.0);\n" \
|
||||
"final_color.b = clamp((color_bright * (tint_color.b * strength)) + (base_color.b * (1.0 - strength)), 0.0, 1.0);\n" \
|
||||
"}\n"
|
||||
|
||||
#define GLSL_SOFTWARE_FADE_EQUATION \
|
||||
"float darkness = R_DoomLightingEquation(lighting);\n" \
|
||||
"if (fade_start != 0.0 || fade_end != 31.0) {\n" \
|
||||
"float fs = fade_start / 31.0;\n" \
|
||||
"float fe = fade_end / 31.0;\n" \
|
||||
"float fd = fe - fs;\n" \
|
||||
"darkness = clamp((darkness - fs) * (1.0 / fd), 0.0, 1.0);\n" \
|
||||
"}\n" \
|
||||
"final_color = mix(final_color, fade_color, darkness);\n"
|
||||
|
||||
#define GLSL_PALETTE_RENDERING \
|
||||
"float tex_pal_idx = texture3D(palette_lookup_tex, vec3((texel * 63.0 + 0.5) / 64.0))[0] * 255.0;\n" \
|
||||
"float z = gl_FragCoord.z / gl_FragCoord.w;\n" \
|
||||
"float light_y = clamp(floor(R_DoomColormap(lighting, z)), 0.0, 31.0);\n" \
|
||||
"vec2 lighttable_coord = vec2((tex_pal_idx + 0.5) / 256.0, (light_y + 0.5) / 32.0);\n" \
|
||||
"vec4 final_color = texture2D(lighttable_tex, lighttable_coord);\n" \
|
||||
"final_color.a = texel.a * poly_color.a;\n" \
|
||||
"gl_FragColor = final_color;\n" \
|
||||
|
||||
#define GLSL_SOFTWARE_FRAGMENT_SHADER \
|
||||
"#ifdef SRB2_PALETTE_RENDERING\n" \
|
||||
"uniform sampler2D tex;\n" \
|
||||
"uniform sampler3D palette_lookup_tex;\n" \
|
||||
"uniform sampler2D lighttable_tex;\n" \
|
||||
"uniform vec4 poly_color;\n" \
|
||||
"uniform float lighting;\n" \
|
||||
GLSL_DOOM_COLORMAP \
|
||||
"void main(void) {\n" \
|
||||
"vec4 texel = texture2D(tex, gl_TexCoord[0].st);\n" \
|
||||
GLSL_PALETTE_RENDERING \
|
||||
"}\n" \
|
||||
"#else\n" \
|
||||
"uniform sampler2D tex;\n" \
|
||||
"uniform vec4 poly_color;\n" \
|
||||
"uniform vec4 tint_color;\n" \
|
||||
"uniform vec4 fade_color;\n" \
|
||||
"uniform float lighting;\n" \
|
||||
"uniform float fade_start;\n" \
|
||||
"uniform float fade_end;\n" \
|
||||
GLSL_DOOM_COLORMAP \
|
||||
GLSL_DOOM_LIGHT_EQUATION \
|
||||
"void main(void) {\n" \
|
||||
"vec4 texel = texture2D(tex, gl_TexCoord[0].st);\n" \
|
||||
"vec4 base_color = texel * poly_color;\n" \
|
||||
"vec4 final_color = base_color;\n" \
|
||||
GLSL_SOFTWARE_TINT_EQUATION \
|
||||
GLSL_SOFTWARE_FADE_EQUATION \
|
||||
"final_color.a = texel.a * poly_color.a;\n" \
|
||||
"gl_FragColor = final_color;\n" \
|
||||
"}\n" \
|
||||
"#endif\0"
|
||||
|
||||
// hand tuned adjustments for light level calculation
|
||||
#define GLSL_FLOOR_FUDGES \
|
||||
"#define STARTMAP_FUDGE 1.06\n" \
|
||||
"#define SCALE_FUDGE 1.15\n"
|
||||
|
||||
#define GLSL_WALL_FUDGES \
|
||||
"#define STARTMAP_FUDGE 1.05\n" \
|
||||
"#define SCALE_FUDGE 2.2\n"
|
||||
|
||||
#define GLSL_FLOOR_FRAGMENT_SHADER \
|
||||
GLSL_FLOOR_FUDGES \
|
||||
GLSL_SOFTWARE_FRAGMENT_SHADER
|
||||
|
||||
#define GLSL_WALL_FRAGMENT_SHADER \
|
||||
GLSL_WALL_FUDGES \
|
||||
GLSL_SOFTWARE_FRAGMENT_SHADER
|
||||
|
||||
// same as above but multiplies results with the lighting value from the
|
||||
// accompanying vertex shader (stored in gl_Color) if model lighting is enabled
|
||||
#define GLSL_MODEL_FRAGMENT_SHADER \
|
||||
GLSL_WALL_FUDGES \
|
||||
"#ifdef SRB2_PALETTE_RENDERING\n" \
|
||||
"uniform sampler2D tex;\n" \
|
||||
"uniform sampler3D palette_lookup_tex;\n" \
|
||||
"uniform sampler2D lighttable_tex;\n" \
|
||||
"uniform vec4 poly_color;\n" \
|
||||
"uniform float lighting;\n" \
|
||||
GLSL_DOOM_COLORMAP \
|
||||
"void main(void) {\n" \
|
||||
"vec4 texel = texture2D(tex, gl_TexCoord[0].st);\n" \
|
||||
"#ifdef SRB2_MODEL_LIGHTING\n" \
|
||||
"texel *= gl_Color;\n" \
|
||||
"#endif\n" \
|
||||
GLSL_PALETTE_RENDERING \
|
||||
"}\n" \
|
||||
"#else\n" \
|
||||
"uniform sampler2D tex;\n" \
|
||||
"uniform vec4 poly_color;\n" \
|
||||
"uniform vec4 tint_color;\n" \
|
||||
"uniform vec4 fade_color;\n" \
|
||||
"uniform float lighting;\n" \
|
||||
"uniform float fade_start;\n" \
|
||||
"uniform float fade_end;\n" \
|
||||
GLSL_DOOM_COLORMAP \
|
||||
GLSL_DOOM_LIGHT_EQUATION \
|
||||
"void main(void) {\n" \
|
||||
"vec4 texel = texture2D(tex, gl_TexCoord[0].st);\n" \
|
||||
"vec4 base_color = texel * poly_color;\n" \
|
||||
"vec4 final_color = base_color;\n" \
|
||||
GLSL_SOFTWARE_TINT_EQUATION \
|
||||
GLSL_SOFTWARE_FADE_EQUATION \
|
||||
"#ifdef SRB2_MODEL_LIGHTING\n" \
|
||||
"final_color *= gl_Color;\n" \
|
||||
"#endif\n" \
|
||||
"final_color.a = texel.a * poly_color.a;\n" \
|
||||
"gl_FragColor = final_color;\n" \
|
||||
"}\n" \
|
||||
"#endif\0"
|
||||
|
||||
//
|
||||
// Water surface shader
|
||||
//
|
||||
// Mostly guesstimated, rather than the rest being built off Software science.
|
||||
// Still needs to distort things underneath/around the water...
|
||||
//
|
||||
|
||||
#define GLSL_WATER_TEXEL \
|
||||
"float water_z = (gl_FragCoord.z / gl_FragCoord.w) / 2.0;\n" \
|
||||
"float a = -pi * (water_z * freq) + (leveltime * speed);\n" \
|
||||
"float sdistort = sin(a) * amp;\n" \
|
||||
"float cdistort = cos(a) * amp;\n" \
|
||||
"vec4 texel = texture2D(tex, vec2(gl_TexCoord[0].s - sdistort, gl_TexCoord[0].t - cdistort));\n"
|
||||
|
||||
#define GLSL_WATER_FRAGMENT_SHADER \
|
||||
GLSL_FLOOR_FUDGES \
|
||||
"const float freq = 0.025;\n" \
|
||||
"const float amp = 0.025;\n" \
|
||||
"const float speed = 2.0;\n" \
|
||||
"const float pi = 3.14159;\n" \
|
||||
"#ifdef SRB2_PALETTE_RENDERING\n" \
|
||||
"uniform sampler2D tex;\n" \
|
||||
"uniform sampler3D palette_lookup_tex;\n" \
|
||||
"uniform sampler2D lighttable_tex;\n" \
|
||||
"uniform vec4 poly_color;\n" \
|
||||
"uniform float lighting;\n" \
|
||||
"uniform float leveltime;\n" \
|
||||
GLSL_DOOM_COLORMAP \
|
||||
"void main(void) {\n" \
|
||||
GLSL_WATER_TEXEL \
|
||||
GLSL_PALETTE_RENDERING \
|
||||
"}\n" \
|
||||
"#else\n" \
|
||||
"uniform sampler2D tex;\n" \
|
||||
"uniform vec4 poly_color;\n" \
|
||||
"uniform vec4 tint_color;\n" \
|
||||
"uniform vec4 fade_color;\n" \
|
||||
"uniform float lighting;\n" \
|
||||
"uniform float fade_start;\n" \
|
||||
"uniform float fade_end;\n" \
|
||||
"uniform float leveltime;\n" \
|
||||
GLSL_DOOM_COLORMAP \
|
||||
GLSL_DOOM_LIGHT_EQUATION \
|
||||
"void main(void) {\n" \
|
||||
GLSL_WATER_TEXEL \
|
||||
"vec4 base_color = texel * poly_color;\n" \
|
||||
"vec4 final_color = base_color;\n" \
|
||||
GLSL_SOFTWARE_TINT_EQUATION \
|
||||
GLSL_SOFTWARE_FADE_EQUATION \
|
||||
"final_color.a = texel.a * poly_color.a;\n" \
|
||||
"gl_FragColor = final_color;\n" \
|
||||
"}\n" \
|
||||
"#endif\0"
|
||||
|
||||
//
|
||||
// Fog block shader
|
||||
//
|
||||
// Alpha of the planes themselves are still slightly off -- see HWR_FogBlockAlpha
|
||||
//
|
||||
|
||||
// The floor fudges are used, but should the wall fudges be used instead? or something inbetween?
|
||||
// or separate values for floors and walls? (need to change more than this shader for that)
|
||||
#define GLSL_FOG_FRAGMENT_SHADER \
|
||||
GLSL_FLOOR_FUDGES \
|
||||
"uniform vec4 tint_color;\n" \
|
||||
"uniform vec4 fade_color;\n" \
|
||||
"uniform float lighting;\n" \
|
||||
"uniform float fade_start;\n" \
|
||||
"uniform float fade_end;\n" \
|
||||
GLSL_DOOM_COLORMAP \
|
||||
GLSL_DOOM_LIGHT_EQUATION \
|
||||
"void main(void) {\n" \
|
||||
"vec4 base_color = gl_Color;\n" \
|
||||
"vec4 final_color = base_color;\n" \
|
||||
GLSL_SOFTWARE_TINT_EQUATION \
|
||||
GLSL_SOFTWARE_FADE_EQUATION \
|
||||
"gl_FragColor = final_color;\n" \
|
||||
"}\0"
|
||||
|
||||
//
|
||||
// Sky fragment shader
|
||||
// Modulates poly_color with gl_Color
|
||||
//
|
||||
#define GLSL_SKY_FRAGMENT_SHADER \
|
||||
"uniform sampler2D tex;\n" \
|
||||
"uniform vec4 poly_color;\n" \
|
||||
"void main(void) {\n" \
|
||||
"gl_FragColor = texture2D(tex, gl_TexCoord[0].st) * gl_Color * poly_color;\n" \
|
||||
"}\0"
|
||||
|
||||
// Shader for the palette rendering postprocess step
|
||||
#define GLSL_PALETTE_POSTPROCESS_FRAGMENT_SHADER \
|
||||
"uniform sampler2D tex;\n" \
|
||||
"uniform sampler3D palette_lookup_tex;\n" \
|
||||
"uniform sampler1D palette_tex;\n" \
|
||||
"void main(void) {\n" \
|
||||
"vec4 texel = texture2D(tex, gl_TexCoord[0].st);\n" \
|
||||
"float tex_pal_idx = texture3D(palette_lookup_tex, vec3((texel * 63.0 + 0.5) / 64.0))[0] * 255.0;\n" \
|
||||
"float palette_coord = (tex_pal_idx + 0.5) / 256.0;\n" \
|
||||
"vec4 final_color = texture1D(palette_tex, palette_coord);\n" \
|
||||
"gl_FragColor = final_color;\n" \
|
||||
"}\0"
|
||||
|
||||
// Applies a palettized colormap fade to tex
|
||||
#define GLSL_UI_COLORMAP_FADE_FRAGMENT_SHADER \
|
||||
"uniform sampler2D tex;\n" \
|
||||
"uniform float lighting;\n" \
|
||||
"uniform sampler3D palette_lookup_tex;\n" \
|
||||
"uniform sampler2D lighttable_tex;\n" \
|
||||
"void main(void) {\n" \
|
||||
"vec4 texel = texture2D(tex, gl_TexCoord[0].st);\n" \
|
||||
"float tex_pal_idx = texture3D(palette_lookup_tex, vec3((texel * 63.0 + 0.5) / 64.0))[0] * 255.0;\n" \
|
||||
"vec2 lighttable_coord = vec2((tex_pal_idx + 0.5) / 256.0, (lighting + 0.5) / 32.0);\n" \
|
||||
"gl_FragColor = texture2D(lighttable_tex, lighttable_coord);\n" \
|
||||
"}\0"
|
||||
|
||||
// For wipes that use additive and subtractive blending.
|
||||
// alpha_factor = 31 * 8 / 10 = 24.8
|
||||
// Calculated based on the use of the "fade" variable from the GETCOLOR macro
|
||||
// in r_data.c:R_CreateFadeColormaps.
|
||||
// However this value created some ugliness in fades to white (special stage entry)
|
||||
// while palette rendering is enabled, so I raised the value just a bit.
|
||||
#define GLSL_UI_TINTED_WIPE_FRAGMENT_SHADER \
|
||||
"uniform sampler2D tex;\n" \
|
||||
"uniform vec4 poly_color;\n" \
|
||||
"const float alpha_factor = 24.875;\n" \
|
||||
"void main(void) {\n" \
|
||||
"vec4 texel = texture2D(tex, gl_TexCoord[0].st);\n" \
|
||||
"vec4 final_color = poly_color;\n" \
|
||||
"float alpha = texel.a;\n" \
|
||||
"if (final_color.a >= 0.5)\n" \
|
||||
"alpha = 1.0 - alpha;\n" \
|
||||
"alpha *= alpha_factor;\n" \
|
||||
"final_color *= alpha;\n" \
|
||||
"final_color.a = 1.0;\n" \
|
||||
"gl_FragColor = final_color;\n" \
|
||||
"}\0"
|
||||
|
||||
//
|
||||
// Generic vertex shader
|
||||
//
|
||||
|
||||
#define GLSL_FALLBACK_VERTEX_SHADER \
|
||||
"void main()\n" \
|
||||
"{\n" \
|
||||
"gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex;\n" \
|
||||
"gl_FrontColor = gl_Color;\n" \
|
||||
"gl_TexCoord[0].xy = gl_MultiTexCoord0.xy;\n" \
|
||||
"gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;\n" \
|
||||
"}\0"
|
||||
|
||||
//
|
||||
// Generic fragment shader
|
||||
//
|
||||
|
||||
#define GLSL_FALLBACK_FRAGMENT_SHADER \
|
||||
"uniform sampler2D tex;\n" \
|
||||
"uniform vec4 poly_color;\n" \
|
||||
"void main(void) {\n" \
|
||||
"gl_FragColor = texture2D(tex, gl_TexCoord[0].st) * poly_color;\n" \
|
||||
"}\0"
|
||||
|
||||
//
|
||||
// Software fragment shader
|
||||
//
|
||||
|
||||
#define GLSL_SOFTWARE_FADE_EQUATION \
|
||||
"float darkness = R_DoomLightingEquation(lighting);\n" \
|
||||
"if (fade_start != 0.0 || fade_end != 31.0) {\n" \
|
||||
"float fs = fade_start / 31.0;\n" \
|
||||
"float fe = fade_end / 31.0;\n" \
|
||||
"float fd = fe - fs;\n" \
|
||||
"darkness = clamp((darkness - fs) * (1.0 / fd), 0.0, 1.0);\n" \
|
||||
"}\n" \
|
||||
"final_color = mix(final_color, fade_color, darkness);\n"
|
||||
|
||||
// same as above but multiplies results with the lighting value from the
|
||||
// accompanying vertex shader (stored in gl_Color)
|
||||
#define GLSL_SOFTWARE_MODEL_LIGHTING_FRAGMENT_SHADER \
|
||||
"uniform sampler2D tex;\n" \
|
||||
"uniform vec4 poly_color;\n" \
|
||||
"uniform vec4 tint_color;\n" \
|
||||
"uniform vec4 fade_color;\n" \
|
||||
"uniform float lighting;\n" \
|
||||
"uniform float fade_start;\n" \
|
||||
"uniform float fade_end;\n" \
|
||||
GLSL_DOOM_COLORMAP \
|
||||
GLSL_DOOM_LIGHT_EQUATION \
|
||||
"void main(void) {\n" \
|
||||
"vec4 texel = texture2D(tex, gl_TexCoord[0].st);\n" \
|
||||
"vec4 base_color = texel * poly_color;\n" \
|
||||
"vec4 final_color = base_color;\n" \
|
||||
GLSL_SOFTWARE_TINT_EQUATION \
|
||||
GLSL_SOFTWARE_FADE_EQUATION \
|
||||
"final_color *= gl_Color;\n" \
|
||||
"final_color.a = texel.a * poly_color.a;\n" \
|
||||
"gl_FragColor = final_color;\n" \
|
||||
"}\0"
|
||||
|
||||
//
|
||||
// Sky fragment shader
|
||||
// Modulates poly_color with gl_Color
|
||||
//
|
||||
#define GLSL_SKY_FRAGMENT_SHADER \
|
||||
"uniform sampler2D tex;\n" \
|
||||
"uniform vec4 poly_color;\n" \
|
||||
"void main(void) {\n" \
|
||||
"gl_FragColor = texture2D(tex, gl_TexCoord[0].st) * gl_Color * poly_color;\n" \
|
||||
"}\0"
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load diff
|
@ -46,6 +46,7 @@
|
|||
#define _CREATE_DLL_ // necessary for Unix AND Windows
|
||||
#include "../../doomdef.h"
|
||||
#include "../hw_drv.h"
|
||||
#include "../../z_zone.h"
|
||||
|
||||
// ==========================================================================
|
||||
// DEFINITIONS
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "i_system.h" // I_GetPreciseTime
|
||||
#include "m_misc.h"
|
||||
#include "st_stuff.h" // st_palette
|
||||
#include "doomstat.h" // singletics
|
||||
|
||||
#ifdef HWRENDER
|
||||
#include "hardware/hw_main.h"
|
||||
|
@ -604,7 +605,7 @@ static void GIF_framewrite(void)
|
|||
UINT16 delay = 0;
|
||||
INT32 startline;
|
||||
|
||||
if (gif_dynamicdelay ==(UINT8) 2)
|
||||
if (gif_dynamicdelay ==(UINT8) 2 && !singletics)
|
||||
{
|
||||
// golden's attempt at creating a "dynamic delay"
|
||||
UINT16 mingifdelay = 10; // minimum gif delay in milliseconds (keep at 10 because gifs can't get more precise).
|
||||
|
@ -617,7 +618,7 @@ static void GIF_framewrite(void)
|
|||
gif_delayus -= frames*(mingifdelay*1000); // remove frames by the amount of milliseconds they take. don't reset to 0, the microseconds help consistency.
|
||||
}
|
||||
}
|
||||
else if (gif_dynamicdelay ==(UINT8) 1)
|
||||
else if (gif_dynamicdelay ==(UINT8) 1 && !singletics)
|
||||
{
|
||||
float delayf = ceil(100.0f/NEWTICRATE);
|
||||
|
||||
|
|
17
src/m_menu.c
17
src/m_menu.c
|
@ -1406,18 +1406,19 @@ static menuitem_t OP_OpenGLOptionsMenu[] =
|
|||
|
||||
{IT_HEADER, NULL, "General", NULL, 51},
|
||||
{IT_STRING|IT_CVAR, NULL, "Shaders", &cv_glshaders, 63},
|
||||
{IT_STRING|IT_CVAR, NULL, "Lack of perspective", &cv_glshearing, 73},
|
||||
{IT_STRING|IT_CVAR, NULL, "Field of view", &cv_fov, 83},
|
||||
{IT_STRING|IT_CVAR, NULL, "Palette rendering", &cv_glpaletterendering, 73},
|
||||
{IT_STRING|IT_CVAR, NULL, "Lack of perspective", &cv_glshearing, 83},
|
||||
{IT_STRING|IT_CVAR, NULL, "Field of view", &cv_fov, 93},
|
||||
|
||||
{IT_HEADER, NULL, "Miscellaneous", NULL, 102},
|
||||
{IT_STRING|IT_CVAR, NULL, "Bit depth", &cv_scr_depth, 114},
|
||||
{IT_STRING|IT_CVAR, NULL, "Texture filter", &cv_glfiltermode, 124},
|
||||
{IT_STRING|IT_CVAR, NULL, "Anisotropic", &cv_glanisotropicmode, 134},
|
||||
{IT_HEADER, NULL, "Miscellaneous", NULL, 112},
|
||||
{IT_STRING|IT_CVAR, NULL, "Bit depth", &cv_scr_depth, 124},
|
||||
{IT_STRING|IT_CVAR, NULL, "Texture filter", &cv_glfiltermode, 134},
|
||||
{IT_STRING|IT_CVAR, NULL, "Anisotropic", &cv_glanisotropicmode, 144},
|
||||
#ifdef ALAM_LIGHTING
|
||||
{IT_SUBMENU|IT_STRING, NULL, "Lighting...", &OP_OpenGLLightingDef, 144},
|
||||
{IT_SUBMENU|IT_STRING, NULL, "Lighting...", &OP_OpenGLLightingDef, 154},
|
||||
#endif
|
||||
#if defined (_WINDOWS) && (!(defined (__unix__) || defined (UNIXCOMMON) || defined (HAVE_SDL)))
|
||||
{IT_STRING|IT_CVAR, NULL, "Fullscreen", &cv_fullscreen, 154},
|
||||
{IT_STRING|IT_CVAR, NULL, "Fullscreen", &cv_fullscreen, 164},
|
||||
#endif
|
||||
};
|
||||
|
||||
|
|
|
@ -1254,7 +1254,7 @@ void M_SaveFrame(void)
|
|||
// paranoia: should be unnecessary without singletics
|
||||
static tic_t oldtic = 0;
|
||||
|
||||
if (oldtic == I_GetTime())
|
||||
if (oldtic == I_GetTime() && !singletics)
|
||||
return;
|
||||
else
|
||||
oldtic = I_GetTime();
|
||||
|
|
|
@ -1134,10 +1134,10 @@ boolean I_InitTcpDriver(void)
|
|||
{
|
||||
I_AddExitFunc(I_ShutdownTcpDriver);
|
||||
#ifdef HAVE_MINIUPNPC
|
||||
if (M_CheckParm("-noUPnP"))
|
||||
UPNP_support = false;
|
||||
else
|
||||
if (M_CheckParm("-useUPnP"))
|
||||
I_InitUPnP();
|
||||
else
|
||||
UPNP_support = false;
|
||||
#endif
|
||||
}
|
||||
return init_tcp_driver;
|
||||
|
|
|
@ -2329,9 +2329,9 @@ boolean P_CheckDeathPitCollide(mobj_t *mo)
|
|||
if (mo->player && mo->player->pflags & PF_GODMODE)
|
||||
return false;
|
||||
|
||||
if (((mo->z <= mo->subsector->sector->floorheight
|
||||
if (((mo->z <= mo->floorz
|
||||
&& ((mo->subsector->sector->flags & MSF_TRIGGERSPECIAL_HEADBUMP) || !(mo->eflags & MFE_VERTICALFLIP)) && (mo->subsector->sector->flags & MSF_FLIPSPECIAL_FLOOR))
|
||||
|| (mo->z + mo->height >= mo->subsector->sector->ceilingheight
|
||||
|| (mo->z + mo->height >= mo->ceilingz
|
||||
&& ((mo->subsector->sector->flags & MSF_TRIGGERSPECIAL_HEADBUMP) || (mo->eflags & MFE_VERTICALFLIP)) && (mo->subsector->sector->flags & MSF_FLIPSPECIAL_CEILING)))
|
||||
&& (mo->subsector->sector->damagetype == SD_DEATHPITTILT
|
||||
|| mo->subsector->sector->damagetype == SD_DEATHPITNOTILT))
|
||||
|
|
|
@ -31,6 +31,10 @@
|
|||
#include "byteptr.h"
|
||||
#include "dehacked.h"
|
||||
|
||||
#ifdef HWRENDER
|
||||
#include "hardware/hw_glob.h" // HWR_ClearLightTables
|
||||
#endif
|
||||
|
||||
//
|
||||
// Graphics.
|
||||
// SRB2 graphics for walls and sprites
|
||||
|
@ -422,6 +426,9 @@ void R_ClearColormaps(void)
|
|||
{
|
||||
// Purged by PU_LEVEL, just overwrite the pointer
|
||||
extra_colormaps = R_CreateDefaultColormap(true);
|
||||
#ifdef HWRENDER
|
||||
HWR_ClearLightTables();
|
||||
#endif
|
||||
}
|
||||
|
||||
//
|
||||
|
|
29
src/r_defs.h
29
src/r_defs.h
|
@ -25,6 +25,10 @@
|
|||
|
||||
#include "screen.h" // MAXVIDWIDTH, MAXVIDHEIGHT
|
||||
|
||||
#ifdef HWRENDER
|
||||
#include "m_aatree.h"
|
||||
#endif
|
||||
|
||||
#include "taglist.h"
|
||||
|
||||
//
|
||||
|
@ -69,6 +73,11 @@ typedef struct extracolormap_s
|
|||
|
||||
lighttable_t *colormap;
|
||||
|
||||
#ifdef HWRENDER
|
||||
// The id of the hardware lighttable. Zero means it does not exist yet.
|
||||
UINT32 gl_lighttable_id;
|
||||
#endif
|
||||
|
||||
#ifdef EXTRACOLORMAPLUMPS
|
||||
lumpnum_t lump; // for colormap lump matching, init to LUMPERROR
|
||||
char lumpname[9]; // for netsyncing
|
||||
|
@ -897,6 +906,26 @@ typedef struct
|
|||
// the [0] is &columnofs[width]
|
||||
} ATTRPACK softwarepatch_t;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable : 4200)
|
||||
#endif
|
||||
|
||||
// a pic is an unmasked block of pixels, stored in horizontal way
|
||||
typedef struct
|
||||
{
|
||||
INT16 width;
|
||||
UINT8 zero; // set to 0 allow autodetection of pic_t
|
||||
// mode instead of patch or raw
|
||||
UINT8 mode; // see pic_mode_t above
|
||||
INT16 height;
|
||||
INT16 reserved1; // set to 0
|
||||
UINT8 data[0];
|
||||
} ATTRPACK pic_t;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(default : 4200)
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma pack()
|
||||
#endif
|
||||
|
|
|
@ -193,6 +193,8 @@ static void R_DrawBlendColumnInCache(column_t *column, UINT8 *cache, texpatch_t
|
|||
{
|
||||
for (; dest < cache + position + count; source++, dest++, is_opaque++)
|
||||
{
|
||||
if (originPatch->alpha <= ASTTextureBlendingThreshold[1] && !(*is_opaque))
|
||||
continue;
|
||||
*dest = ASTBlendPaletteIndexes(*dest, *source, originPatch->style, originPatch->alpha);
|
||||
*is_opaque = true;
|
||||
}
|
||||
|
@ -237,6 +239,8 @@ static void R_DrawBlendFlippedColumnInCache(column_t *column, UINT8 *cache, texp
|
|||
{
|
||||
for (; dest < cache + position + count; --source, dest++, is_opaque++)
|
||||
{
|
||||
if (originPatch->alpha <= ASTTextureBlendingThreshold[1] && !(*is_opaque))
|
||||
continue;
|
||||
*dest = ASTBlendPaletteIndexes(*dest, *source, originPatch->style, originPatch->alpha);
|
||||
*is_opaque = true;
|
||||
}
|
||||
|
|
|
@ -495,6 +495,7 @@
|
|||
<ClCompile Include="..\hardware\hw_md2load.c" />
|
||||
<ClCompile Include="..\hardware\hw_md3load.c" />
|
||||
<ClCompile Include="..\hardware\hw_model.c" />
|
||||
<ClCompile Include="..\hardware\hw_shaders.c" />
|
||||
<ClCompile Include="..\hardware\r_opengl\r_opengl.c" />
|
||||
<ClCompile Include="..\lua_colorlib.c" />
|
||||
<ClCompile Include="..\r_bbox.c" />
|
||||
|
|
|
@ -751,6 +751,12 @@
|
|||
<ClCompile Include="..\hardware\hw_model.c">
|
||||
<Filter>Hw_Hardware</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\hardware\hw_shaders.c">
|
||||
<Filter>Hw_Hardware</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\hardware\u_list.c">
|
||||
<Filter>Hw_Hardware</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\filesrch.c">
|
||||
<Filter>I_Interface</Filter>
|
||||
</ClCompile>
|
||||
|
|
|
@ -74,7 +74,7 @@ void *hwSym(const char *funcName,void *handle)
|
|||
{
|
||||
void *funcPointer = NULL;
|
||||
#ifdef HWRENDER
|
||||
if (0 == strcmp("SetPalette", funcName))
|
||||
if (0 == strcmp("SetTexturePalette", funcName))
|
||||
funcPointer = &OglSdlSetPalette;
|
||||
|
||||
GETFUNC(Init);
|
||||
|
@ -87,7 +87,7 @@ void *hwSym(const char *funcName,void *handle)
|
|||
GETFUNC(SetTexture);
|
||||
GETFUNC(UpdateTexture);
|
||||
GETFUNC(DeleteTexture);
|
||||
GETFUNC(ReadRect);
|
||||
GETFUNC(ReadScreenTexture);
|
||||
GETFUNC(GClipRect);
|
||||
GETFUNC(ClearMipMapCache);
|
||||
GETFUNC(SetSpecialState);
|
||||
|
@ -97,21 +97,23 @@ void *hwSym(const char *funcName,void *handle)
|
|||
GETFUNC(SetTransform);
|
||||
GETFUNC(PostImgRedraw);
|
||||
GETFUNC(FlushScreenTextures);
|
||||
GETFUNC(StartScreenWipe);
|
||||
GETFUNC(EndScreenWipe);
|
||||
GETFUNC(DoScreenWipe);
|
||||
GETFUNC(DrawIntermissionBG);
|
||||
GETFUNC(DrawScreenTexture);
|
||||
GETFUNC(MakeScreenTexture);
|
||||
GETFUNC(MakeScreenFinalTexture);
|
||||
GETFUNC(DrawScreenFinalTexture);
|
||||
|
||||
GETFUNC(CompileShaders);
|
||||
GETFUNC(CleanShaders);
|
||||
GETFUNC(InitShaders);
|
||||
GETFUNC(LoadShader);
|
||||
GETFUNC(CompileShader);
|
||||
GETFUNC(SetShader);
|
||||
GETFUNC(UnSetShader);
|
||||
|
||||
GETFUNC(SetShaderInfo);
|
||||
GETFUNC(LoadCustomShader);
|
||||
|
||||
GETFUNC(SetPaletteLookup);
|
||||
GETFUNC(CreateLightTable);
|
||||
GETFUNC(ClearLightTables);
|
||||
GETFUNC(SetScreenPalette);
|
||||
|
||||
#else //HWRENDER
|
||||
if (0 == strcmp("FinishUpdate", funcName))
|
||||
|
|
|
@ -1295,6 +1295,14 @@ void I_FinishUpdate(void)
|
|||
#ifdef HWRENDER
|
||||
else if (rendermode == render_opengl)
|
||||
{
|
||||
// Final postprocess step of palette rendering, after everything else has been drawn.
|
||||
if (HWR_ShouldUsePaletteRendering())
|
||||
{
|
||||
HWD.pfnMakeScreenTexture(HWD_SCREENTEXTURE_GENERIC2);
|
||||
HWD.pfnSetShader(HWR_GetShaderFromTarget(SHADER_PALETTE_POSTPROCESS));
|
||||
HWD.pfnDrawScreenTexture(HWD_SCREENTEXTURE_GENERIC2, NULL, 0);
|
||||
HWD.pfnUnSetShader();
|
||||
}
|
||||
OglSdlFinishUpdate(cv_vidwait.value);
|
||||
}
|
||||
#endif
|
||||
|
@ -1865,32 +1873,34 @@ void VID_StartupOpenGL(void)
|
|||
HWD.pfnSetTexture = hwSym("SetTexture",NULL);
|
||||
HWD.pfnUpdateTexture = hwSym("UpdateTexture",NULL);
|
||||
HWD.pfnDeleteTexture = hwSym("DeleteTexture",NULL);
|
||||
HWD.pfnReadRect = hwSym("ReadRect",NULL);
|
||||
HWD.pfnReadScreenTexture= hwSym("ReadScreenTexture",NULL);
|
||||
HWD.pfnGClipRect = hwSym("GClipRect",NULL);
|
||||
HWD.pfnClearMipMapCache = hwSym("ClearMipMapCache",NULL);
|
||||
HWD.pfnSetSpecialState = hwSym("SetSpecialState",NULL);
|
||||
HWD.pfnSetPalette = hwSym("SetPalette",NULL);
|
||||
HWD.pfnSetTexturePalette= hwSym("SetTexturePalette",NULL);
|
||||
HWD.pfnGetTextureUsed = hwSym("GetTextureUsed",NULL);
|
||||
HWD.pfnDrawModel = hwSym("DrawModel",NULL);
|
||||
HWD.pfnCreateModelVBOs = hwSym("CreateModelVBOs",NULL);
|
||||
HWD.pfnSetTransform = hwSym("SetTransform",NULL);
|
||||
HWD.pfnPostImgRedraw = hwSym("PostImgRedraw",NULL);
|
||||
HWD.pfnFlushScreenTextures=hwSym("FlushScreenTextures",NULL);
|
||||
HWD.pfnStartScreenWipe = hwSym("StartScreenWipe",NULL);
|
||||
HWD.pfnEndScreenWipe = hwSym("EndScreenWipe",NULL);
|
||||
HWD.pfnDoScreenWipe = hwSym("DoScreenWipe",NULL);
|
||||
HWD.pfnDrawIntermissionBG=hwSym("DrawIntermissionBG",NULL);
|
||||
HWD.pfnDrawScreenTexture= hwSym("DrawScreenTexture",NULL);
|
||||
HWD.pfnMakeScreenTexture= hwSym("MakeScreenTexture",NULL);
|
||||
HWD.pfnMakeScreenFinalTexture=hwSym("MakeScreenFinalTexture",NULL);
|
||||
HWD.pfnDrawScreenFinalTexture=hwSym("DrawScreenFinalTexture",NULL);
|
||||
|
||||
HWD.pfnCompileShaders = hwSym("CompileShaders",NULL);
|
||||
HWD.pfnCleanShaders = hwSym("CleanShaders",NULL);
|
||||
HWD.pfnInitShaders = hwSym("InitShaders",NULL);
|
||||
HWD.pfnLoadShader = hwSym("LoadShader",NULL);
|
||||
HWD.pfnCompileShader = hwSym("CompileShader",NULL);
|
||||
HWD.pfnSetShader = hwSym("SetShader",NULL);
|
||||
HWD.pfnUnSetShader = hwSym("UnSetShader",NULL);
|
||||
|
||||
HWD.pfnSetShaderInfo = hwSym("SetShaderInfo",NULL);
|
||||
HWD.pfnLoadCustomShader = hwSym("LoadCustomShader",NULL);
|
||||
|
||||
HWD.pfnSetPaletteLookup = hwSym("SetPaletteLookup",NULL);
|
||||
HWD.pfnCreateLightTable = hwSym("CreateLightTable",NULL);
|
||||
HWD.pfnClearLightTables = hwSym("ClearLightTables",NULL);
|
||||
HWD.pfnSetScreenPalette = hwSym("SetScreenPalette",NULL);
|
||||
|
||||
vid.glstate = HWD.pfnInit() ? VID_GL_LIBRARY_LOADED : VID_GL_LIBRARY_ERROR; // let load the OpenGL library
|
||||
|
||||
|
|
|
@ -232,7 +232,9 @@ void OglSdlFinishUpdate(boolean waitvbl)
|
|||
|
||||
// Sryder: We need to draw the final screen texture again into the other buffer in the original position so that
|
||||
// effects that want to take the old screen can do so after this
|
||||
HWR_DrawScreenFinalTexture(realwidth, realheight);
|
||||
// Generic2 has the screen image without palette rendering brightness adjustments.
|
||||
// Using that here will prevent brightness adjustments being applied twice.
|
||||
DrawScreenTexture(HWD_SCREENTEXTURE_GENERIC2, NULL, 0);
|
||||
}
|
||||
|
||||
EXPORT void HWRAPI(OglSdlSetPalette) (RGBA_t *palette)
|
||||
|
|
|
@ -227,8 +227,8 @@ void ST_doPaletteStuff(void)
|
|||
palette = 0;
|
||||
|
||||
#ifdef HWRENDER
|
||||
if (rendermode == render_opengl)
|
||||
palette = 0; // No flashpals here in OpenGL
|
||||
if (rendermode == render_opengl && !HWR_ShouldUsePaletteRendering())
|
||||
palette = 0; // Don't set the palette to a flashpal in OpenGL's truecolor mode
|
||||
#endif
|
||||
|
||||
if (palette != st_palette)
|
||||
|
@ -2889,7 +2889,7 @@ void ST_Drawer(void)
|
|||
//25/08/99: Hurdler: palette changes is done for all players,
|
||||
// not only player1! That's why this part
|
||||
// of code is moved somewhere else.
|
||||
if (rendermode == render_soft)
|
||||
if (rendermode == render_soft || HWR_ShouldUsePaletteRendering())
|
||||
#endif
|
||||
if (rendermode != render_none) ST_doPaletteStuff();
|
||||
|
||||
|
|
|
@ -821,10 +821,7 @@ static void W_ReadFileShaders(wadfile_t *wadfile)
|
|||
{
|
||||
#ifdef HWRENDER
|
||||
if (rendermode == render_opengl && (vid.glstate == VID_GL_LIBRARY_LOADED))
|
||||
{
|
||||
HWR_LoadCustomShadersFromFile(numwadfiles - 1, W_FileHasFolders(wadfile));
|
||||
HWR_CompileShaders();
|
||||
}
|
||||
#else
|
||||
(void)wadfile;
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue