Merge pull request 'Remerge fixed palette renderer' (#200) from fixpalshader into next

Reviewed-on: https://codeberg.org/NepDisk/blankart/pulls/200
This commit is contained in:
NepDisk 2025-12-16 02:28:55 +01:00
commit 44445e1bc0
23 changed files with 1485 additions and 983 deletions

View file

@ -11,5 +11,6 @@ target_sources(SRB2SDL2 PRIVATE
hw_model.c
u_list.c
hw_batching.c
hw_shaders.c
r_opengl/r_opengl.c
)

View file

@ -93,7 +93,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)
{
@ -132,7 +132,7 @@ void HWR_ProcessPolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPt
polygonArray[polygonArraySize].polyFlags = PolyFlags;
polygonArray[polygonArraySize].texture = current_texture;
polygonArray[polygonArraySize].brightmap = current_brightmap;
polygonArray[polygonArraySize].shader = shader;
polygonArray[polygonArraySize].shader = (shader_target != -1) ? HWR_GetShaderFromTarget(shader_target) : shader_target;
polygonArray[polygonArraySize].horizonSpecial = horizonSpecial;
polygonArraySize++;
@ -141,8 +141,7 @@ void HWR_ProcessPolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPt
}
else
{
if (shader)
HWD.pfnSetShader(shader);
HWD.pfnSetShader((shader_target != SHADER_NONE) ? HWR_GetShaderFromTarget(shader_target) : shader_target);
HWD.pfnDrawPolygon(pSurf, pOutVerts, iNumPts, PolyFlags);
}
}

View file

@ -39,6 +39,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)
@ -56,7 +64,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;
@ -128,7 +136,7 @@ static void HWR_DrawColumnInCache(const column_t *patchcol, UINT8 *block, GLMipm
texelu16 = (UINT16)((alpha<<8) | texel);
memcpy(dest, &texelu16, sizeof(UINT16));
break;
case 3 : colortemp = V_GetColor(texel);
case 3 : colortemp = palette[texel];
if ((originPatch != NULL) && (originPatch->style != AST_COPY))
{
RGBA_t rgbatexel;
@ -137,7 +145,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);
case 4 : colortemp = palette[texel];
colortemp.s.alpha = alpha;
if ((originPatch != NULL) && (originPatch->style != AST_COPY))
{
@ -167,7 +175,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;
@ -238,7 +246,7 @@ static void HWR_DrawFlippedColumnInCache(const column_t *patchcol, UINT8 *block,
texelu16 = (UINT16)((alpha<<8) | texel);
memcpy(dest, &texelu16, sizeof(UINT16));
break;
case 3 : colortemp = V_GetColor(texel);
case 3 : colortemp = palette[texel];
if ((originPatch != NULL) && (originPatch->style != AST_COPY))
{
RGBA_t rgbatexel;
@ -247,7 +255,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);
case 4 : colortemp = palette[texel];
colortemp.s.alpha = alpha;
if ((originPatch != NULL) && (originPatch->style != AST_COPY))
{
@ -291,10 +299,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
@ -320,7 +331,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);
}
}
@ -339,12 +350,14 @@ 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;
@ -362,6 +375,8 @@ static void HWR_DrawTexturePatchInCache(GLMipmap_t *mipmap,
if (patch->originy > texture->height || (patch->originy + height) < 0)
return; // patch not located within texture's y bounds, ignore
palette = HWR_GetTexturePalette();
// patch is actually inside the texture!
// now check if texture is partly off-screen and adjust accordingly
@ -416,7 +431,7 @@ static void HWR_DrawTexturePatchInCache(GLMipmap_t *mipmap,
pblockheight, blockmodulo,
yfracstep, scale_y,
patch, height,
bpp);
bpp, palette);
}
}
@ -463,6 +478,9 @@ static void HWR_GenerateTexture(GLMapTexture_t *grtex, INT32 texnum, boolean noe
INT32 i, idx;
boolean skyspecial = false; //poor hack for Legacy large skies..
RGBA_t *palette;
palette = HWR_GetTexturePalette();
texture = textures[texnum];
grtex->mipmap.flags = TF_CHROMAKEYED | TF_WRAPXY;
@ -479,7 +497,10 @@ static void HWR_GenerateTexture(GLMapTexture_t *grtex, INT32 texnum, boolean noe
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;
if (!noencoremap && encoremap)
colormap += COLORMAP_REMAPOFFSET;
@ -498,7 +519,7 @@ static void HWR_GenerateTexture(GLMapTexture_t *grtex, INT32 texnum, boolean noe
INT32 j;
RGBA_t col;
col = V_GetColor(HWR_PATCHES_CHROMAKEY_COLORINDEX);
col = palette[HWR_PATCHES_CHROMAKEY_COLORINDEX];
for (idx = 0, j = 0; j < blockheight; j++)
{
for (i = 0; i < blockwidth; i++, idx++)
@ -1008,19 +1029,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
// --------------------------------------------------------------------------
@ -1382,6 +1390,7 @@ static void HWR_DrawPicInCache(UINT8 *block, INT32 pblockwidth, INT32 pblockheig
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;
@ -1408,12 +1417,12 @@ static void HWR_DrawPicInCache(UINT8 *block, INT32 pblockwidth, INT32 pblockheig
dest += sizeof(UINT16);
break;
case 3 :
col = V_GetColor(texel);
col = palette[texel];
memcpy(dest, &col, sizeof(RGBA_t)-sizeof(UINT8));
dest += sizeof(RGBA_t)-sizeof(UINT8);
break;
case 4 :
memcpy(dest, &V_GetColor(texel), sizeof(RGBA_t));
memcpy(dest, &palette[texel], sizeof(RGBA_t));
dest += sizeof(RGBA_t);
break;
}
@ -1523,6 +1532,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),
@ -1540,7 +1550,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++;
@ -1614,4 +1624,211 @@ 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;
}
// remap the palette from 2.1 to 2.2 indices in compatmode
RGBA_t *palcopy = NULL;
if (wadfiles[WADFILENUM(lumpnum)]->compatmode)
{
palcopy = malloc(sizeof(*palcopy)*256);
memcpy(palcopy, RGBA_converted, sizeof(*palcopy)*256);
}
if (palcopy)
{
for (i = 0; i < 256; i++)
{
RGBA_converted[i].rgba = palcopy[R_InvPaletteRemap(i)].rgba;
}
free(palcopy);
}
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

View file

@ -22,6 +22,12 @@ extern "C" {
#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
// ==========================================================================
@ -135,33 +141,30 @@ 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_MODEL_LIGHTING,
SHADER_WATER,
SHADER_FOG,
SHADER_SKY,
SHADER_PALETTE_POSTPROCESS,
SHADER_UI_COLORMAP_FADE,
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
@ -290,6 +293,7 @@ struct FSurfaceInfo
RGBA_t PolyColor;
RGBA_t TintColor;
RGBA_t FadeColor;
UINT32 LightTableId;
FLightInfo LightInfo;
};
typedef struct FSurfaceInfo FSurfaceInfo;
@ -297,7 +301,7 @@ typedef struct FSurfaceInfo FSurfaceInfo;
#define GL_DEFAULTMIX 0x00000000
#define GL_DEFAULTFOG 0x19000000
//Hurdler: added for backward compatibility
// Various settings and states for the rendering backend.
enum hwdsetspecialstate
{
HWD_SET_MODEL_LIGHTING = 1,
@ -309,15 +313,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.
@ -343,6 +345,20 @@ 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
HWD_SCREENTEXTURE_VHS,
NUMSCREENTEXTURES, // (generic3 is unused if palette rendering is disabled)
};
typedef enum hwdscreentexture hwdscreentexture_t;
#ifdef __cplusplus
} // extern "C"
#endif

View file

@ -534,12 +534,26 @@ void HWR_FadeScreenMenuBack(UINT16 color, UINT8 strength)
if (color & 0xFF00) // Do 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;
}
Surf.PolyColor.rgba = UINT2RGBA(0x01010160);
Surf.PolyColor.s.alpha = (strength*8);
}
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];
}
HWD.pfnDrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Modulated|PF_Translucent|PF_NoDepthTest);
@ -620,7 +634,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);
@ -716,8 +731,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);
@ -912,6 +928,7 @@ void HWR_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color)
float fx, fy, fw, fh;
UINT8 alphalevel = ((color & V_ALPHAMASK) >> V_ALPHASHIFT);
UINT8 blendmode = ((color & V_BLENDMASK) >> V_BLENDSHIFT);
RGBA_t *palette = HWR_GetTexturePalette();
// 3--2
// | /|
@ -927,7 +944,7 @@ void HWR_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color)
{
if (x == 0 && y == 0 && w == BASEVIDWIDTH*FRACUNIT && h == BASEVIDHEIGHT*FRACUNIT)
{
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;
@ -955,7 +972,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];
flags = HWR_GetBlendModeFlag(blendmode+1)|PF_Modulated|PF_NoDepthTest|PF_NoTexture;
@ -1044,6 +1061,7 @@ static inline boolean saveTGA(const char *file_name, void *buffer,
UINT8 *HWR_GetScreenshot(INT32 scale)
{
static UINT8 *buf = NULL;
int tex = HWR_ShouldUsePaletteRendering() ? HWD_SCREENTEXTURE_GENERIC3 : HWD_SCREENTEXTURE_GENERIC2;
buf = realloc(buf, (vid.width/scale)*(vid.height/scale)*3);
@ -1051,7 +1069,7 @@ UINT8 *HWR_GetScreenshot(INT32 scale)
return NULL;
// returns 24bit 888 RGB
HWD.pfnReadScreenFinalTexture(buf, scale);
HWD.pfnReadScreenTexture(tex, (void *)buf, scale);
return buf;
}

View file

@ -33,7 +33,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);
@ -44,7 +44,7 @@ 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(ReadScreenFinalTexture) (UINT8 * restrict dest, INT32 scale);
EXPORT void HWRAPI(ReadScreenTexture) (int tex, UINT8 *restrict dest, INT32 scale);
EXPORT void HWRAPI(GClipRect) (INT32 minx, INT32 miny, INT32 maxx, INT32 maxy, float nearclip);
EXPORT void HWRAPI(ClearMipMapCache) (void);
@ -58,26 +58,27 @@ EXPORT void HWRAPI(SetTransform) (FTransform *stransform);
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(MakeIntermissionBG) (void);
EXPORT void HWRAPI(DrawIntermissionBG) (void);
EXPORT void HWRAPI(MakeScreenTexture) (void);
EXPORT void HWRAPI(DoScreenWipe) (int wipeStart, int wipeEnd);
EXPORT void HWRAPI(DrawScreenTexture) (int tex, FSurfaceInfo *surf, FBITFIELD polyflags);
EXPORT void HWRAPI(RenderVhsEffect) (INT16 upbary, INT16 downbary, UINT8 updistort, UINT8 downdistort, UINT8 barsize);
EXPORT void HWRAPI(MakeScreenFinalTexture) (void);
EXPORT void HWRAPI(DrawScreenFinalTexture) (int width, int height);
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
@ -88,7 +89,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;
@ -99,10 +100,10 @@ struct hwdriver_s
SetTexture pfnSetTexture;
UpdateTexture pfnUpdateTexture;
DeleteTexture pfnDeleteTexture;
ReadScreenFinalTexture pfnReadScreenFinalTexture;
ReadScreenTexture pfnReadScreenTexture;
GClipRect pfnGClipRect;
ClearMipMapCache pfnClearMipMapCache;
SetSpecialState pfnSetSpecialState;//Hurdler: added for backward compatibility
SetSpecialState pfnSetSpecialState;
DrawModel pfnDrawModel;
CreateModelVBOs pfnCreateModelVBOs;
SetTransform pfnSetTransform;
@ -112,23 +113,24 @@ struct hwdriver_s
#endif
PostImgRedraw pfnPostImgRedraw;
FlushScreenTextures pfnFlushScreenTextures;
StartScreenWipe pfnStartScreenWipe;
EndScreenWipe pfnEndScreenWipe;
DoScreenWipe pfnDoScreenWipe;
MakeIntermissionBG pfnMakeIntermissionBG;
DrawIntermissionBG pfnDrawIntermissionBG;
MakeScreenTexture pfnMakeScreenTexture;
RenderVhsEffect pfnRenderVhsEffect;
MakeScreenFinalTexture pfnMakeScreenFinalTexture;
DrawScreenTexture pfnDrawScreenTexture;
MakeScreenTexture pfnMakeScreenTexture;
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;

View file

@ -108,6 +108,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);
@ -133,7 +135,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);
// --------
// hw_draw.c
@ -141,6 +146,20 @@ 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[];
#ifdef __cplusplus
} // extern "C"
#endif

View file

@ -131,26 +131,6 @@ static line_t *gl_linedef;
static sector_t *gl_frontsector;
static sector_t *gl_backsector;
// --------------------------------------------------------------------------
// STUFF FOR THE PROJECTION CODE
// --------------------------------------------------------------------------
FTransform atransform;
// duplicates of the main code, set after R_SetupFrame() passed them into sharedstruct,
// copied here for local use
static fixed_t dup_viewx, dup_viewy, dup_viewz;
static angle_t dup_viewangle;
static float gl_viewx, gl_viewy, gl_viewz;
float gl_viewsin, gl_viewcos;
// Maybe not necessary with the new T&L code (needs to be checked!)
static float gl_viewludsin, gl_viewludcos; // look up down kik test
static float gl_fovlud;
static angle_t gl_aimingangle;
static void HWR_SetTransformAiming(FTransform *trans, player_t *player, boolean skybox);
// Render stats
precise_t ps_hw_skyboxtime = 0;
precise_t ps_hw_nodesorttime = 0;
@ -172,13 +152,38 @@ precise_t ps_hw_batchdrawtime = 0;
boolean gl_init = false;
boolean gl_maploaded = false;
boolean gl_sessioncommandsadded = false;
boolean gl_shadersavailable = true;
// 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;
// duplicates of the main code, set after R_SetupFrame() passed them into sharedstruct,
// copied here for local use
static fixed_t dup_viewx, dup_viewy, dup_viewz;
static angle_t dup_viewangle;
static float gl_viewx, gl_viewy, gl_viewz;
float gl_viewsin, gl_viewcos;
// Maybe not necessary with the new T&L code (needs to be checked!)
static float gl_viewludsin, gl_viewludcos; // look up down kik test
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);
}
@ -295,6 +300,10 @@ void HWR_Lighting(FSurfaceInfo *Surface, INT32 light_level, extracolormap_t *col
poly_color.s.blue = (UINT8)blue;
}
// Shift the lightlevel for Palette rendering mode to replicate software´s limited 32 lightlevels
if (HWR_ShouldUsePaletteRendering())
light_level = (light_level >> LIGHTSEGSHIFT) << LIGHTSEGSHIFT;
// Clamp the light level, since it can sometimes go out of the 0-255 range from animations
light_level = min(max(light_level, cv_secbright.value), 255);
@ -310,6 +319,11 @@ void HWR_Lighting(FSurfaceInfo *Surface, INT32 light_level, extracolormap_t *col
Surface->LightInfo.newfade = (colormap != NULL) ? !!(colormap->flags & CMF_NEWFADE) : false;
Surface->LightInfo.directional = (maplighting.directional == true && directional == true);
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
@ -399,7 +413,7 @@ static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, bool
static FOutVector *planeVerts = NULL;
static UINT16 numAllocedPlaneVerts = 0;
INT32 shader = SHADER_DEFAULT;
INT32 shader = SHADER_NONE;
// no convex poly were generated for this subsector
if (!xsub->planepoly)
@ -728,7 +742,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, P_SectorUsesDirectionalLighting(gl_frontsector));
@ -939,7 +953,7 @@ static void HWR_DrawSkyWall(FOutVector *wallVerts, FSurfaceInfo *Surf)
wallVerts[0].t = wallVerts[1].t = 0;
wallVerts[0].s = wallVerts[3].s = 0;
wallVerts[2].s = wallVerts[1].s = 0;
// this no longer sets top/bottom coords, this should be done before caling the function
// this no longer sets top/bottom coords, this should be done before calling the function
HWR_ProjectWall(wallVerts, Surf, PF_Invisible|PF_NoTexture, 255, NULL);
// PF_Invisible so it's not drawn into the colour buffer
// PF_NoTexture for no texture
@ -2361,7 +2375,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;
@ -3126,7 +3140,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_ReverseSubtract;
INT32 shader = SHADER_DEFAULT;
INT32 shader = SHADER_NONE;
UINT8 i;
INT32 heightsec, phs;
SINT8 flip = P_MobjFlip(thing);
@ -3318,7 +3332,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;
@ -3605,6 +3619,7 @@ static void HWR_DrawBoundingBox(gl_vissprite_t *vis)
{
FOutVector v[24];
FSurfaceInfo Surf = {0};
RGBA_t *palette = HWR_GetTexturePalette();
//
// create a cube (side view)
@ -3644,7 +3659,7 @@ static void HWR_DrawBoundingBox(gl_vissprite_t *vis)
v[003].y = v[004].y = v[005].y = v[011].y = v[012].y = v[013].y =
v[017].y = v[020].y = v[021].y = v[025].y = v[026].y = v[027].y = vis->gzt; // top
Surf.PolyColor = V_GetColor(R_GetBoundingBoxColor(vis->mobj));
Surf.PolyColor = palette[R_GetBoundingBoxColor(vis->mobj)];
HWR_ProcessPolygon(&Surf, v, 24, PF_Modulated|PF_NoTexture|PF_WireFrame, SHADER_NONE, false);
}
@ -3906,7 +3921,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;
@ -3981,7 +3996,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;
@ -4468,7 +4483,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++)
{
@ -5585,7 +5599,9 @@ 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);
}
@ -5671,8 +5687,6 @@ static void HWR_DrawSkyBackground(player_t *player)
HWD.pfnUnSetShader();
HWD.pfnDrawPolygon(NULL, v, 4, 0);
}
HWD.pfnSetShader(SHADER_DEFAULT);
}
@ -5788,13 +5802,7 @@ 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_ClearClipper(void)
@ -5816,6 +5824,7 @@ void HWR_RenderSkyboxView(player_t *player)
camera_t *thiscam = &camera[viewnum];
const float fpov = FIXED_TO_FLOAT(cv_fov[viewssnum].value+player->fovadd);
if (!HWR_ShouldUsePaletteRendering())
{
// do we really need to save player (is it not the same)?
player_t *saved_player = stplyr;
@ -6159,6 +6168,56 @@ void HWR_RenderPlayerView(void)
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 (pMasterPalette != NULL && 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
@ -6172,6 +6231,9 @@ void HWR_LoadLevel(void)
HWR_ClearSkyDome();
HWR_BuildSkyDome();
if (HWR_ShouldUsePaletteRendering())
HWR_SetMapPalette();
gl_maploaded = true;
}
@ -6179,7 +6241,7 @@ 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}};
CV_PossibleValue_t glshaders_cons_t[] = {{0, "Off"}, {1, "On"}, {2, "Ignore custom shaders"}, {0, NULL}};
#ifdef BAD_MODEL_OPTIONS
static CV_PossibleValue_t glmodelinterpolation_cons_t[] = {{0, "Off"}, {1, "Sometimes"}, {2, "Always"}, {0, NULL}};
#endif
@ -6227,16 +6289,65 @@ 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);
CV_PossibleValue_t glpalettedepth_cons_t[] = {{16, "16 bits"}, {24, "24 bits"}, {0, NULL}};
void CV_glpaletterendering_OnChange(void);
void CV_glpalettedepth_OnChange(void);
consvar_t cv_glpaletterendering = CVAR_INIT ("gr_paletteshader", "Off", CV_CALL|CV_SAVE, 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;
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);
}
void CV_glmodellighting_OnChange(void);
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();
}
void CV_glpaletterendering_OnChange(void)
{
ONLY_IF_GL_LOADED
if (gl_shadersavailable)
{
HWR_CompileShaders();
HWR_TogglePaletteRendering();
}
}
void CV_glpalettedepth_OnChange(void);
void CV_glpalettedepth_OnChange(void)
{
ONLY_IF_GL_LOADED
// refresh the screen palette
if (HWR_ShouldUsePaletteRendering())
HWR_SetPalette(pLocalPalette);
}
void CV_glshaders_OnChange(void);
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
@ -6271,6 +6382,9 @@ void HWR_AddCommands(void)
CV_RegisterVar(&cv_glbatching);
CV_RegisterVar(&cv_glanisotropicmode);
CV_RegisterVar(&cv_glpaletterendering);
CV_RegisterVar(&cv_glpalettedepth);
}
void HWR_AddSessionCommands(void)
@ -6289,6 +6403,8 @@ void HWR_Startup(void)
{
CONS_Printf("HWR_Startup()...\n");
textureformat = patchformat = GL_TEXFMT_RGBA;
HWR_InitPolyPool();
HWR_AddSessionCommands();
HWR_InitMapTextures();
@ -6297,14 +6413,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;
}
@ -6399,7 +6513,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, P_SectorUsesDirectionalLighting(gl_frontsector));
@ -6437,7 +6551,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;
@ -6463,7 +6577,8 @@ void HWR_DoPostProcessor(player_t *player)
}
// Capture the screen for intermission and screen waving
HWD.pfnMakeScreenTexture();
if (gamestate != GS_INTERMISSION)
HWD.pfnMakeScreenTexture(HWD_SCREENTEXTURE_GENERIC1);
if (r_splitscreen) // Not supported in splitscreen - someone want to add support?
return;
@ -6508,6 +6623,10 @@ void HWR_DoPostProcessor(player_t *player)
}
}
HWD.pfnPostImgRedraw(v);
// Capture the screen again for screen waving on the intermission
if (gamestate != GS_INTERMISSION)
HWD.pfnMakeScreenTexture(HWD_SCREENTEXTURE_GENERIC1);
}
// Flipping of the screen isn't done here anymore
}
@ -6515,23 +6634,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();
}
void HWR_MakeIntermissionBG(void)
{
HWD.pfnMakeIntermissionBG();
HWD.pfnMakeScreenTexture(HWD_SCREENTEXTURE_WIPE_END);
}
void HWR_DrawIntermissionBG(void)
{
HWD.pfnDrawIntermissionBG();
HWD.pfnDrawScreenTexture(HWD_SCREENTEXTURE_GENERIC1, NULL, 0);
}
//
@ -6576,7 +6690,7 @@ void HWR_DoWipe(UINT8 wipenum, UINT8 scrnnum)
return;
HWR_GetFadeMask(wipelumpnum);
HWD.pfnDoScreenWipe();
HWD.pfnDoScreenWipe(HWD_SCREENTEXTURE_WIPE_START, HWD_SCREENTEXTURE_WIPE_END);
}
void HWR_DoTintedWipe(UINT8 wipenum, UINT8 scrnnum)
@ -6592,190 +6706,14 @@ void HWR_RenderVhsEffect(INT16 upbary, INT16 downbary, UINT8 updistort, UINT8 do
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, (wadfiles[i]->type == RET_PK3));
}
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);
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

View file

@ -70,6 +70,7 @@ 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);
boolean HWR_OverrideObjectLightLevel(mobj_t *thing, INT32 *lightlevel);
void HWR_Lighting(FSurfaceInfo *Surface, INT32 light_level, extracolormap_t *colormap, const boolean directional);
UINT8 HWR_FogBlockAlpha(INT32 light, extracolormap_t *colormap); // Let's see if this can work
@ -79,13 +80,7 @@ FBITFIELD HWR_GetBlendModeFlag(INT32 ast);
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[];
@ -120,6 +115,8 @@ extern consvar_t cv_glspritebillboarding;
extern consvar_t cv_glskydome;
extern consvar_t cv_glbatching;
extern consvar_t cv_glpaletterendering;
extern consvar_t cv_glpalettedepth;
extern float gl_viewwidth, gl_viewheight, gl_baseviewwindowy;

View file

@ -391,8 +391,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);
@ -413,13 +411,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++;
}
}
}
@ -1714,7 +1718,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);
fixed_t floorClip = spr->mobj->terrain ? spr->mobj->terrain->floorClip : 0;

View file

@ -34,7 +34,7 @@ static struct {
{GLSL_DEFAULT_VERTEX_SHADER, GLSL_WALL_FRAGMENT_SHADER},
// Model shader
{GLSL_DEFAULT_VERTEX_SHADER, GLSL_SOFTWARE_FRAGMENT_SHADER},
{GLSL_DEFAULT_VERTEX_SHADER, GLSL_WALL_FRAGMENT_SHADER},
// Model shader + diffuse lighting from above
{GLSL_MODEL_LIGHTING_VERTEX_SHADER, GLSL_SOFTWARE_MODEL_LIGHTING_FRAGMENT_SHADER},
@ -434,6 +434,7 @@ customshaderxlat_t shaderxlat[] =
{"WallTexture", SHADER_WALL},
{"Sprite", SHADER_SPRITE},
{"Model", SHADER_MODEL},
{"ModelLight", SHADER_MODEL_LIGHTING},
{"WaterRipple", SHADER_WATER},
{"Fog", SHADER_FOG},
{"Sky", SHADER_SKY},
@ -444,11 +445,13 @@ customshaderxlat_t shaderxlat[] =
void HWR_LoadAllCustomShaders(void)
{
/*
INT32 i;
// read every custom shader
//for (i = 0; i < numwadfiles; i++)
// HWR_LoadCustomShadersFromFile(i, (type == RET_PK3)));
for (i = 0; i < numwadfiles; i++)
HWR_LoadCustomShadersFromFile(i, (type == RET_PK3)));
*/
}
void HWR_LoadCustomShadersFromFile(UINT16 wadnum, boolean PK3)

442
src/hardware/hw_shaders.h Normal file
View file

@ -0,0 +1,442 @@
// 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"
// reinterpretation of sprite lighting for models
// it's a combination of how it works for normal sprites & papersprites
#define GLSL_MODEL_LIGHTING_VERTEX_SHADER \
"uniform float lighting;\n" \
"uniform vec3 light_dir;\n" \
"uniform float light_contrast;\n" \
"uniform float light_backlight;\n" \
"void main()\n" \
"{\n" \
"gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex;\n" \
"float light = lighting;\n" \
"if (length(light_dir) > 0.000001) {\n" \
"mat4 m4 = gl_ProjectionMatrix * gl_ModelViewMatrix;\n" \
"mat3 m3 = mat3( m4[0].xyz, m4[1].xyz, m4[2].xyz );\n" \
"float extralight = -dot(normalize(gl_Normal * m3), normalize(light_dir));\n" \
"extralight *= light_contrast - light_backlight;\n" \
"extralight *= lighting / 255.0;\n" \
"light += extralight * 2.5;\n" \
"}\n" \
"light = clamp(light / 255.0, 0.0, 1.0);\n" \
"gl_FrontColor = vec4(light, light, light, 1.0);\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 (mix(tint_color.a, 0.0, brightmap_mix) > 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 * mix(tint_color.a, 0.0, brightmap_mix));\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(final_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" \
"if (newfade)\n" \
"{\n" \
"float colorBrightness = sqrt((final_color.r * final_color.r) + (final_color.g * final_color.g) + (final_color.b * final_color.b));\n" \
"float fogBrightness = sqrt((fade_color.r * fade_color.r) + (fade_color.g * fade_color.g) + (fade_color.b * fade_color.b));\n" \
"float colorIntensity = 0.0;\n" \
"if (colorBrightness < fogBrightness) {\n" \
"colorIntensity = 1.0 - min(final_color.r, min(final_color.g, final_color.b));\n" \
"colorIntensity = abs(colorIntensity - (1.0 - max(fade_color.r, max(fade_color.g, fade_color.b))));\n" \
"} else {\n" \
"colorIntensity = max(final_color.r, max(final_color.g, final_color.b));\n" \
"colorIntensity = abs(colorIntensity - min(fade_color.r, min(fade_color.g, fade_color.b)));\n" \
"}\n" \
"colorIntensity *= darkness;\n" \
"colorIntensity *= fade_color.a * 10.0;\n" \
"if (abs(final_color.r - fade_color.r) <= colorIntensity) {\n" \
"final_color.r = fade_color.r;\n" \
"} else if (final_color.r < fade_color.r) {\n" \
"final_color.r += colorIntensity;\n" \
"} else {\n" \
"final_color.r -= colorIntensity;\n" \
"}\n" \
"if (abs(final_color.g - fade_color.g) <= colorIntensity) {\n" \
"final_color.g = fade_color.g;\n" \
"} else if (final_color.g < fade_color.g) {\n" \
"final_color.g += colorIntensity;\n" \
"} else {\n" \
"final_color.g -= colorIntensity;\n" \
"}\n" \
"if (abs(final_color.b - fade_color.b) <= colorIntensity) {\n" \
"final_color.b = fade_color.b;\n" \
"} else if (final_color.b < fade_color.b) {\n" \
"final_color.b += colorIntensity;\n" \
"} else {\n" \
"final_color.b -= colorIntensity;\n" \
"}\n" \
"} else {\n" \
"final_color = mix(final_color, fade_color, darkness);\n" \
"}\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(final_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 sampler2D brightmap;\n" \
"uniform vec4 poly_color;\n" \
"uniform float lighting;\n" \
"uniform sampler3D palette_lookup_tex;\n" \
"uniform sampler2D lighttable_tex;\n" \
GLSL_DOOM_COLORMAP \
"void main(void) {\n" \
"vec4 texel = texture2D(tex, gl_TexCoord[0].st);\n" \
"float brightmap_mix = floor(texture2D(brightmap, gl_TexCoord[0].st).r);\n" \
"float light_gain = (255.0 - lighting) * brightmap_mix;\n" \
"float final_lighting = lighting + light_gain;\n" \
GLSL_PALETTE_RENDERING \
"}\n" \
"#else\n" \
"uniform sampler2D tex;\n" \
"uniform sampler2D brightmap;\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 bool newfade;\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" \
"float brightmap_mix = floor(texture2D(brightmap, gl_TexCoord[0].st).r);\n" \
"float light_gain = (255.0 - lighting) * brightmap_mix;\n" \
"float final_lighting = lighting + light_gain;\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 \
"#version 120\n" \
GLSL_FLOOR_FUDGES \
GLSL_SOFTWARE_FRAGMENT_SHADER
#define GLSL_WALL_FRAGMENT_SHADER \
"#version 120\n" \
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)
#define GLSL_SOFTWARE_MODEL_LIGHTING_FRAGMENT_SHADER \
GLSL_WALL_FUDGES \
"#ifdef SRB2_PALETTE_RENDERING\n" \
"uniform sampler2D tex;\n" \
"uniform sampler2D brightmap;\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" \
"float final_lighting = gl_Color.r * 255.0;\n" \
"float brightmap_mix = floor(texture2D(brightmap, gl_TexCoord[0].st).r);\n" \
"float light_gain = (255.0 - final_lighting) * brightmap_mix;\n" \
"final_lighting += light_gain;\n" \
GLSL_PALETTE_RENDERING \
"}\n" \
"#else\n" \
"uniform sampler2D tex;\n" \
"uniform sampler2D brightmap;\n" \
"uniform vec4 poly_color;\n" \
"uniform vec4 tint_color;\n" \
"uniform vec4 fade_color;\n" \
"uniform float fade_start;\n" \
"uniform float fade_end;\n" \
"uniform bool newfade;\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" \
"float final_lighting = gl_Color.r * 255.0;\n" \
"float brightmap_mix = floor(texture2D(brightmap, gl_TexCoord[0].st).r);\n" \
"float light_gain = (255.0 - final_lighting) * brightmap_mix;\n" \
"final_lighting += light_gain;\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"
//
// 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 \
"#version 120\n" \
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 sampler2D brightmap;\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 \
"float brightmap_mix = floor(texture2D(brightmap, gl_TexCoord[0].st).r);\n" \
"float light_gain = (255.0 - lighting) * brightmap_mix;\n" \
"float final_lighting = lighting + light_gain;\n" \
GLSL_PALETTE_RENDERING \
"}\n" \
"#else\n" \
"uniform sampler2D tex;\n" \
"uniform sampler2D brightmap;\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 bool newfade;\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" \
"float brightmap_mix = floor(texture2D(brightmap, gl_TexCoord[0].st).r);\n" \
"float light_gain = (255.0 - lighting) * brightmap_mix;\n" \
"float final_lighting = lighting + light_gain;\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 \
"#version 120\n" \
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" \
"uniform bool newfade;\n" \
GLSL_DOOM_COLORMAP \
GLSL_DOOM_LIGHT_EQUATION \
"void main(void) {\n" \
"vec4 base_color = gl_Color;\n" \
"vec4 final_color = base_color;\n" \
"float brightmap_mix = 0.0;\n" \
"float light_gain = 0.0;\n" \
"float final_lighting = lighting + light_gain;\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"
//
// 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"
//
// 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

View file

@ -37,6 +37,7 @@
#define _CREATE_DLL_ // necessary for Unix AND Windows
#include "../../doomdef.h"
#include "../hw_drv.h"
#include "../../z_zone.h"
#ifdef __cplusplus
extern "C" {
@ -53,10 +54,10 @@ extern "C" {
#define DEBUG_TO_FILE // output debugging msgs to ogllog.txt
// todo: find some way of getting SDL to log to ogllog.txt, without
// interfering with r_opengl.dll
#ifdef HAVE_SDL
#undef DEBUG_TO_FILE
#endif
// interfering with r_opengl.dll r_opengl.dll is gone since over a decade lol
//#ifdef HAVE_SDL
//#undef DEBUG_TO_FILE
//#endif
//#if defined(HAVE_SDL) && !defined(_DEBUG)
//#undef DEBUG_TO_FILE
//#endif

View file

@ -8834,7 +8834,8 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate)
{
// Reset the palette now all fades have been done
if (rendermode != render_none)
V_ReloadPalette(); // Set the level palette
//V_ReloadPalette(); // Set the level palette
V_SetPaletteLump(GetPalette()); // the above does not *set* the screen palette
if (!(reloadinggamestate || titlemapinaction))
{
@ -8904,6 +8905,9 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate)
// Free GPU textures before freeing patches.
if (rendermode == render_opengl && (vid.glstate == VID_GL_LIBRARY_LOADED))
HWR_ClearAllTextures();
// Delete light table textures
HWR_ClearLightTables();
#endif
G_FreeGhosts(); // ghosts are allocated with PU_LEVEL

View file

@ -32,7 +32,7 @@
#include "dehacked.h"
#ifdef HWRENDER
#include "hardware/hw_glob.h"
#include "hardware/hw_glob.h" // HWR_ClearLightTables
#endif
// DRRR

View file

@ -76,6 +76,11 @@ struct extracolormap_t
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

View file

@ -66,7 +66,7 @@ void *hwSym(const char *funcName,void *handle)
{
void *funcPointer = NULL;
#ifdef HWRENDER
if (fastcmp("SetPalette", funcName))
if (fastcmp("SetTexturePalette", funcName))
funcPointer = FUNCPTRCAST(&OglSdlSetPalette);
GETFUNC(Init);
@ -79,7 +79,7 @@ void *hwSym(const char *funcName,void *handle)
GETFUNC(SetTexture);
GETFUNC(UpdateTexture);
GETFUNC(DeleteTexture);
GETFUNC(ReadScreenFinalTexture);
GETFUNC(ReadScreenTexture);
GETFUNC(GClipRect);
GETFUNC(ClearMipMapCache);
GETFUNC(SetSpecialState);
@ -89,23 +89,24 @@ void *hwSym(const char *funcName,void *handle)
GETFUNC(SetTransform);
GETFUNC(PostImgRedraw);
GETFUNC(FlushScreenTextures);
GETFUNC(StartScreenWipe);
GETFUNC(EndScreenWipe);
GETFUNC(DoScreenWipe);
GETFUNC(MakeIntermissionBG);
GETFUNC(DrawIntermissionBG);
GETFUNC(MakeScreenTexture);
GETFUNC(RenderVhsEffect);
GETFUNC(MakeScreenFinalTexture);
GETFUNC(DrawScreenTexture);
GETFUNC(MakeScreenTexture);
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 (fastcmp("FinishUpdate", funcName))

View file

@ -1318,7 +1318,17 @@ 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
}
@ -1757,34 +1767,34 @@ static void Impl_InitOpenGL(void)
*(void**)&HWD.pfnSetTexture = hwSym("SetTexture",NULL);
*(void**)&HWD.pfnUpdateTexture = hwSym("UpdateTexture",NULL);
*(void**)&HWD.pfnDeleteTexture = hwSym("DeleteTexture",NULL);
*(void**)&HWD.pfnReadScreenFinalTexture=hwSym("ReadScreenFinalTexture",NULL);
*(void**)&HWD.pfnReadScreenTexture= hwSym("ReadScreenTexture",NULL);
*(void**)&HWD.pfnGClipRect = hwSym("GClipRect",NULL);
*(void**)&HWD.pfnClearMipMapCache = hwSym("ClearMipMapCache",NULL);
*(void**)&HWD.pfnSetSpecialState = hwSym("SetSpecialState",NULL);
*(void**)&HWD.pfnSetPalette = hwSym("SetPalette",NULL);
*(void**)&HWD.pfnSetTexturePalette= hwSym("SetTexturePalette",NULL);
*(void**)&HWD.pfnGetTextureUsed = hwSym("GetTextureUsed",NULL);
*(void**)&HWD.pfnDrawModel = hwSym("DrawModel",NULL);
*(void**)&HWD.pfnCreateModelVBOs = hwSym("CreateModelVBOs",NULL);
*(void**)&HWD.pfnSetTransform = hwSym("SetTransform",NULL);
*(void**)&HWD.pfnPostImgRedraw = hwSym("PostImgRedraw",NULL);
*(void**)&HWD.pfnFlushScreenTextures=hwSym("FlushScreenTextures",NULL);
*(void**)&HWD.pfnStartScreenWipe = hwSym("StartScreenWipe",NULL);
*(void**)&HWD.pfnEndScreenWipe = hwSym("EndScreenWipe",NULL);
*(void**)&HWD.pfnDoScreenWipe = hwSym("DoScreenWipe",NULL);
*(void**)&HWD.pfnDrawIntermissionBG=hwSym("DrawIntermissionBG",NULL);
*(void**)&HWD.pfnMakeIntermissionBG=hwSym("MakeIntermissionBG",NULL);
*(void**)&HWD.pfnDrawScreenTexture= hwSym("DrawScreenTexture",NULL);
*(void**)&HWD.pfnMakeScreenTexture= hwSym("MakeScreenTexture",NULL);
*(void**)&HWD.pfnRenderVhsEffect = hwSym("RenderVhsEffect",NULL);
*(void**)&HWD.pfnMakeScreenFinalTexture=hwSym("MakeScreenFinalTexture",NULL);
*(void**)&HWD.pfnDrawScreenFinalTexture=hwSym("DrawScreenFinalTexture",NULL);
*(void**)&HWD.pfnCompileShaders = hwSym("CompileShaders",NULL);
*(void**)&HWD.pfnCleanShaders = hwSym("CleanShaders",NULL);
*(void**)&HWD.pfnInitShaders = hwSym("InitShaders",NULL);
*(void**)&HWD.pfnLoadShader = hwSym("LoadShader",NULL);
*(void**)&HWD.pfnCompileShader = hwSym("CompileShader",NULL);
*(void**)&HWD.pfnSetShader = hwSym("SetShader",NULL);
*(void**)&HWD.pfnUnSetShader = hwSym("UnSetShader",NULL);
*(void**)&HWD.pfnSetShaderInfo = hwSym("SetShaderInfo",NULL);
*(void**)&HWD.pfnLoadCustomShader = hwSym("LoadCustomShader",NULL);
*(void**)&HWD.pfnSetPaletteLookup = hwSym("SetPaletteLookup",NULL);
*(void**)&HWD.pfnCreateLightTable = hwSym("CreateLightTable",NULL);
*(void**)&HWD.pfnClearLightTables = hwSym("ClearLightTables",NULL);
*(void**)&HWD.pfnSetScreenPalette = hwSym("SetScreenPalette",NULL);
if (HWD.pfnInit())
vid.glstate = VID_GL_LIBRARY_LOADED;
@ -1793,6 +1803,7 @@ static void Impl_InitOpenGL(void)
vid.glstate = VID_GL_LIBRARY_ERROR;
CV_StealthSet(&cv_renderer, "Software");
rendermode = render_soft;
if (setrenderneeded)

View file

@ -192,7 +192,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)

View file

@ -145,8 +145,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)
@ -970,7 +970,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();

View file

@ -1075,10 +1075,7 @@ UINT16 W_InitFile(const char *filename, boolean mainfile, boolean startup, boole
#ifdef HWRENDER
// Read shaders from file
if (rendermode == render_opengl && (vid.glstate == VID_GL_LIBRARY_LOADED))
{
HWR_LoadCustomShadersFromFile(numwadfiles - 1, (type == RET_PK3));
HWR_CompileShaders();
}
#endif // HWRENDER
// check if compatmode is needed

View file

@ -381,7 +381,7 @@ void Y_ConsiderScreenBuffer(void)
else if (rendermode == render_opengl)
{
y_screenbuffer = Z_Malloc(0, PU_STATIC, NULL);
HWR_MakeIntermissionBG();
HWR_DrawIntermissionBG();
}
#endif
}