- converted all boolean parameters of the shader into a single flag word.

- discarded the idea of transient palettes because the maintenance here stood in no relation to the savingd.
This commit is contained in:
Christoph Oelckers 2019-10-19 22:46:37 +02:00
parent 17816b0f63
commit 7d2f61db2e
11 changed files with 166 additions and 131 deletions

View file

@ -32,7 +32,7 @@ extern void Polymost_prepare_loadboard(void);
void polymost_outputGLDebugMessage(uint8_t severity, const char* format, ...);
//void phex(char v, char *s);
void uploadbasepalette(int32_t basepalnum, bool transient = false);
void uploadbasepalette(int32_t basepalnum);
void uploadpalswaps(int count, int32_t *palookupnum);
void polymost_drawsprite(int32_t snum);
void polymost_drawmaskwall(int32_t damaskwallcnt);

View file

@ -717,7 +717,7 @@ void paletteSetColorTable(int32_t id, uint8_t const * const table, bool transien
#ifdef USE_OPENGL
if (videoGetRenderMode() >= REND_POLYMOST)
{
uploadbasepalette(id, transient);
uploadbasepalette(id);
}
#endif
}

View file

@ -366,7 +366,7 @@ static void resizeglcheck(void)
}
}
void uploadbasepalette(int32_t basepalnum, bool transient) // transient palettes are used by movies and should not affect the engine state. All other palettes only get set at game startup.
void uploadbasepalette(int32_t basepalnum)
{
if (!basepaltable[basepalnum])
{
@ -382,7 +382,7 @@ void uploadbasepalette(int32_t basepalnum, bool transient) // transient palettes
basepalWFullBrightInfo[i*4+3] = 0-(IsPaletteIndexFullbright(i) != 0);
}
GLInterface.SetPaletteData(basepalnum, basepalWFullBrightInfo, transient);
GLInterface.SetPaletteData(basepalnum, basepalWFullBrightInfo);
}
// Used by RRRA fog hackery - the only place changing the palswaps at run time.

View file

@ -70,11 +70,8 @@ void PaletteManager::DeleteAll()
{
if (pal.swaptexture) delete pal.swaptexture;
}
if (transientpalette.paltexture) delete transientpalette.paltexture;
if (palswapTexture) delete palswapTexture;
palswapTexture = nullptr;
transientpalette.paltexture = nullptr;
transientpalette.crc32 = -1;
palettes.Reset();
palswaps.Reset();
lastindex = ~0u;
@ -168,26 +165,12 @@ unsigned PaletteManager::FindPalswap(const uint8_t* paldata)
//
//===========================================================================
void PaletteManager::SetPalette(int index, const uint8_t* data, bool transient)
void PaletteManager::SetPalette(int index, const uint8_t* data)
{
// New palettes may only be added if declared transient or on startup.
// Otherwise this would require a renderer reset to flush out the textures affected by the change.
if (index < 0 || index > 255) return; // invalid index - ignore.
if (transient)
{
// Transient palettes do not get stored in the list because it is assumed that they won't be needed for long.
// Only clear the texture if the palette is different.
if (memcmp(data, transientpalette.colors, 1024))
{
memcpy(transientpalette.colors, data, 1024);
if (transientpalette.paltexture) delete transientpalette.paltexture;
transientpalette.paltexture = nullptr;
}
transientpalette.crc32 = index;
palettemap[index] = 0;
return;
}
palettemap[index] = FindPalette(data);
if (index == 0)
{
@ -203,19 +186,7 @@ void PaletteManager::SetPalette(int index, const uint8_t* data, bool transient)
void PaletteManager::BindPalette(int index)
{
if (index == transientpalette.crc32)
{
if (transientpalette.paltexture == nullptr)
{
auto p = GLInterface.NewTexture();
p->CreateTexture(256, 1, false, false);
p->LoadTexture((uint8_t*)transientpalette.colors);
p->SetSampler(SamplerNoFilterClampXY);
transientpalette.paltexture = p;
}
inst->BindTexture(2, transientpalette.paltexture);
}
else if (palettemap[index] < palettes.Size())
if (palettemap[index] < palettes.Size())
{
auto uindex = palettemap[index];
if (uindex != lastindex)

View file

@ -1,23 +1,38 @@
#pragma once
#include "PalEntry.h"
class PolymostShader;
enum PRSFlags
{
RF_ColorOnly = 1,
RF_UsePalette = 2,
RF_DetailMapping = 4,
RF_GlowMapping = 8,
RF_Brightmapping = 16,
RF_NPOTEmulation = 32,
RF_ShadeInterpolate = 64,
RF_FogDisabled = 128,
RF_HICTINT_Grayscale = 0x10000,
RF_HICTINT_Invert = 0x20000,
RF_HICTINT_Colorize = 0x40000,
RF_HICTINT_BLEND_Screen = 0x80000,
RF_HICTINT_BLEND_Overlay = 0x100000,
RF_HICTINT_BLEND_Hardlight = 0x200000,
RF_HICTINT_BLENDMASK = RF_HICTINT_BLEND_Screen | RF_HICTINT_BLEND_Overlay | RF_HICTINT_BLEND_Hardlight,
};
struct PolymostRenderState
{
float Clamp[2];
float Shade;
float NumShades = 64.f;
float VisFactor = 128.f;
float UseColorOnly;
float UsePalette = 1.f;
float UseDetailMapping;
float UseGlowMapping;
float NPOTEmulation;
int Flags = 0;
float NPOTEmulationFactor = 1.f;
float NPOTEmulationXOffset;
float Brightness = 1.f;
float ShadeInterpolate = 1.f;
float FogColor[4];
PalEntry FogColor;
void Apply(PolymostShader *shader);
};

View file

@ -135,19 +135,13 @@ bool PolymostShader::Load(const char * name, const char * vert_prog, const char
{
if (!FShader::Load(name, vert_prog, frag_prog)) return false;
Clamp.Init(hShader, "u_clamp");
Flags.Init(hShader, "u_flags");
Shade.Init(hShader, "u_shade");
NumShades.Init(hShader, "u_numShades");
VisFactor.Init(hShader, "u_visFactor");
UseColorOnly.Init(hShader, "u_useColorOnly");
UsePalette.Init(hShader, "u_usePalette");
UseDetailMapping.Init(hShader, "u_useDetailMapping");
UseGlowMapping.Init(hShader, "u_useGlowMapping");
NPOTEmulation.Init(hShader, "u_npotEmulation");
NPOTEmulationFactor.Init(hShader, "u_npotEmulationFactor");
NPOTEmulationXOffset.Init(hShader, "u_npotEmulationXOffset");
Brightness.Init(hShader, "u_brightness");
ShadeInterpolate.Init(hShader, "u_shadeInterpolate");
FogColor.Init(hShader, "u_fogColor");
RotMatrix.Init(hShader, "u_rotMatrix");

View file

@ -35,20 +35,14 @@ public:
class PolymostShader : public FShader
{
public:
FBufferedUniform2f Clamp;
FBufferedUniform1i Flags;
FBufferedUniform1f Shade;
FBufferedUniform1f NumShades;
FBufferedUniform1f VisFactor;
FBufferedUniform1f UseColorOnly;
FBufferedUniform1f UsePalette;
FBufferedUniform1f UseDetailMapping;
FBufferedUniform1f UseGlowMapping;
FBufferedUniform1f NPOTEmulation;
FBufferedUniform1f NPOTEmulationFactor;
FBufferedUniform1f NPOTEmulationXOffset;
FBufferedUniform1f Brightness;
FBufferedUniform4f FogColor;
FBufferedUniform1f ShadeInterpolate;
FBufferedUniformPalEntry FogColor;
FUniformMatrix4f RotMatrix;
FUniformMatrix4f ModelMatrix;

View file

@ -1,5 +1,28 @@
#pragma once
class FBufferedUniform1i
{
int mBuffer;
int mIndex;
public:
void Init(GLuint hShader, const GLchar* name)
{
mIndex = glGetUniformLocation(hShader, name);
mBuffer = 0;
}
void Set(int newvalue)
{
if (newvalue != mBuffer)
{
mBuffer = newvalue;
glUniform1i(mIndex, newvalue);
}
}
};
class FBufferedUniform1f
{
float mBuffer;
@ -77,6 +100,35 @@ public:
}
};
class FBufferedUniformPalEntry
{
PalEntry mBuffer;
int mIndex;
public:
void Init(GLuint hShader, const GLchar* name)
{
mIndex = glGetUniformLocation(hShader, name);
mBuffer = 0;
}
void Set(PalEntry newvalue)
{
if (newvalue != mBuffer)
{
mBuffer = newvalue;
glUniform4f(mIndex,
newvalue.r * (1 / 255.f),
newvalue.g * (1 / 255.f),
newvalue.b * (1 / 255.f),
newvalue.a * (1 / 255.f));
}
}
};
class FUniformMatrix4f
{
int mIndex;

View file

@ -230,7 +230,6 @@ void GLInstance::Draw(EDrawType type, size_t start, size_t count)
if (activeShader == polymostShader)
{
renderState.UsePalette = texv && texv->isIndexed();
renderState.Apply(polymostShader);
}
glBegin(primtypes[type]);
@ -386,18 +385,6 @@ void GLInstance::SetDepthFunc(int func)
glDepthFunc(f[func]);
}
void GLInstance::SetFadeColor(PalEntry color)
{
renderState.FogColor[0] = color.r * (1 / 255.f);
renderState.FogColor[1] = color.g * (1 / 255.f);
renderState.FogColor[2] = color.b * (1 / 255.f);
};
void GLInstance::SetFadeDisable(bool on)
{
renderState.FogColor[3] = on;
}
void GLInstance::SetColorMask(bool on)
{
glColorMask(on, on, on, on);
@ -494,18 +481,13 @@ void GLInstance::SetPalswap(int index)
void PolymostRenderState::Apply(PolymostShader* shader)
{
shader->Clamp.Set(Clamp);
shader->Flags.Set(Flags);
shader->Shade.Set(Shade);
shader->NumShades.Set(NumShades);
shader->VisFactor.Set(VisFactor);
shader->UseColorOnly.Set(UseColorOnly);
shader->UsePalette.Set(UsePalette);
shader->UseDetailMapping.Set(UseDetailMapping);
shader->UseGlowMapping.Set(UseGlowMapping);
shader->NPOTEmulation.Set(NPOTEmulation);
shader->Flags.Set(Flags);
shader->NPOTEmulationFactor.Set(NPOTEmulationFactor);
shader->NPOTEmulationXOffset.Set(NPOTEmulationXOffset);
shader->ShadeInterpolate.Set(ShadeInterpolate);
shader->Brightness.Set(Brightness);
shader->FogColor.Set(FogColor);

View file

@ -55,10 +55,6 @@ class PaletteManager
uint32_t lastsindex = ~0u;
int numshades = 1;
// Keep the short lived movie palettes out of the palette list for ease of maintenance.
// Since it is transient this doesn't need to be preserved if it changes, unlike the other palettes which need to be preserved as references for the texture management.
PaletteData transientpalette = { -1 };
// All data is being stored in contiguous blocks that can be used as uniform buffers as-is.
TArray<PaletteData> palettes;
TArray<PalswapData> palswaps;
@ -76,7 +72,7 @@ public:
{}
~PaletteManager();
void DeleteAll();
void SetPalette(int index, const uint8_t *data, bool transient);
void SetPalette(int index, const uint8_t *data);
void SetPalswapData(int index, const uint8_t* data, int numshades);
void BindPalette(int index);
@ -278,8 +274,6 @@ public:
}
void SetDepthFunc(int func);
void SetFadeColor(PalEntry color);
void SetFadeDisable(bool on);
void SetColorMask(bool on);
void SetDepthMask(bool on);
void SetBlendFunc(int src, int dst);
@ -298,9 +292,9 @@ public:
void ReadPixels(int w, int h, uint8_t* buffer);
void SetPaletteData(int index, const uint8_t* data, bool transient)
void SetPaletteData(int index, const uint8_t* data)
{
palmanager.SetPalette(index, data, transient);
palmanager.SetPalette(index, data);
}
void SetPalswapData(int index, const uint8_t* data, int numshades)
@ -312,13 +306,14 @@ public:
int GetClamp()
{
return int(renderState.Clamp[0] + 2*renderState.Clamp[1]);
return 0;// int(renderState.Clamp[0] + 2 * renderState.Clamp[1]);
}
void SetClamp(int clamp)
{
renderState.Clamp[0] = clamp & 1;
renderState.Clamp[1] = !!(clamp & 2);
// This option is totally pointless and should be removed.
//renderState.Clamp[0] = clamp & 1;
//renderState.Clamp[1] = !!(clamp & 2);
}
void SetShade(int32_t shade, int numshades)
@ -332,31 +327,56 @@ public:
renderState.VisFactor = visibility * fviewingrange * (1.f / (64.f * 65536.f));
}
void UseColorOnly(bool useColorOnly)
void UseColorOnly(bool yes)
{
renderState.UseColorOnly = useColorOnly;
if (yes) renderState.Flags |= RF_ColorOnly;
else renderState.Flags &= ~RF_ColorOnly;
}
void UseDetailMapping(bool useDetailMapping)
void UseDetailMapping(bool yes)
{
renderState.UseDetailMapping = useDetailMapping;
if (yes) renderState.Flags |= RF_DetailMapping;
else renderState.Flags &= ~RF_DetailMapping;
}
void UseGlowMapping(bool useGlowMapping)
void UseGlowMapping(bool yes)
{
renderState.UseGlowMapping = useGlowMapping;
if (yes) renderState.Flags |= RF_GlowMapping;
else renderState.Flags &= ~RF_GlowMapping;
}
void SetNpotEmulation(bool npotEmulation, float factor, float xOffset)
void UseBrightmaps(bool yes)
{
renderState.NPOTEmulation = npotEmulation;
if (yes) renderState.Flags |= RF_Brightmapping;
else renderState.Flags &= ~RF_Brightmapping;
}
void SetNpotEmulation(bool yes, float factor, float xOffset)
{
if (yes)
{
renderState.Flags |= RF_NPOTEmulation;
renderState.NPOTEmulationFactor = factor;
renderState.NPOTEmulationXOffset = xOffset;
}
else renderState.Flags &= ~RF_NPOTEmulation;
}
void SetShadeInterpolate(int32_t shadeInterpolate)
void SetShadeInterpolate(int32_t yes)
{
renderState.ShadeInterpolate = shadeInterpolate;
if (yes) renderState.Flags |= RF_ShadeInterpolate;
else renderState.Flags &= ~RF_ShadeInterpolate;
}
void SetFadeColor(PalEntry color)
{
renderState.FogColor = color;
};
void SetFadeDisable(bool yes)
{
if (!yes) renderState.Flags |= RF_FogDisabled;
else renderState.Flags &= ~RF_FogDisabled;
}
void SetBrightness(int brightness)

View file

@ -1,5 +1,23 @@
#version 330
const int RF_ColorOnly = 1;
const int RF_UsePalette = 2;
const int RF_DetailMapping = 4;
const int RF_GlowMapping = 8;
const int RF_Brightmapping = 16;
const int RF_NPOTEmulation = 32;
const int RF_ShadeInterpolate = 64;
const int RF_FogDisabled = 128;
const int RF_HICTINT_Grayscale = 0x10000;
const int RF_HICTINT_Invert = 0x20000;
const int RF_HICTINT_Colorize = 0x40000;
const int RF_HICTINT_BLEND_Screen = 0x80000;
const int RF_HICTINT_BLEND_Overlay = 0x100000;
const int RF_HICTINT_BLEND_Hardlight = 0x200000;
const int RF_HICTINT_BLENDMASK = RF_HICTINT_BLEND_Screen | RF_HICTINT_BLEND_Overlay | RF_HICTINT_BLEND_Hardlight;
//s_texture points to an indexed color texture
uniform sampler2D s_texture;
//s_palswap is the palette swap texture where u is the color index and v is the shade
@ -10,27 +28,17 @@ uniform sampler2D s_palette;
uniform sampler2D s_detail;
uniform sampler2D s_glow;
uniform vec2 u_clamp;
uniform float u_shade;
uniform float u_numShades;
uniform float u_visFactor;
uniform float u_fogEnabled;
uniform int u_flags;
uniform float u_useColorOnly;
uniform float u_usePalette;
uniform float u_npotEmulation;
uniform float u_npotEmulationFactor;
uniform float u_npotEmulationXOffset;
uniform float u_shadeInterpolate;
uniform float u_brightness;
uniform vec4 u_fogColor;
uniform float u_useDetailMapping;
uniform float u_useGlowMapping;
uniform int u_tinteffect;
uniform vec3 u_tintcolor;
uniform vec3 u_tintmodulate;
in vec4 v_color;
in float v_distance;
@ -71,13 +79,13 @@ vec4 convertColor(vec4 color, int effect, vec3 tint)
{
#if 0
if (effect & HICTINT_GRAYSCALE)
if (effect & RF_HICTINT_Grayscale)
{
float g = grayscale(color);
color = vec4(g, g, g, color.a);
}
if (effect & HICTINT_INVERT)
if (effect & RF_HICTINT_Invert)
{
color = vec4(1.0 - color.r, 1.0 - color.g, 1.0 - color.b);
}
@ -85,26 +93,26 @@ vec4 convertColor(vec4 color, int effect, vec3 tint)
vec3 tcol = color.rgb * 255.0; // * 255.0 to make it easier to reuse the integer math.
tint *= 255.0;
if (effect & HICTINT_COLORIZE)
if (effect & RF_HICTINT_Colorize)
{
tcol.b = min(((tcol.b) * tint.r) / 64.0, 255.0);
tcol.g = min(((tcol.g) * tint.g) / 64.0, 255.0);
tcol.r = min(((tcol.r) * tint.b) / 64.0, 255.0);
}
switch (effect & HICTINT_BLENDMASK)
switch (effect & RF_HICTINT_BLENDMASK)
{
case HICTINT_BLEND_SCREEN:
case RF_HICTINT_BLEND_Screen:
tcol.b = 255.0 - (((255.0 - tcol.b) * (255.0 - tint.r)) / 256.0);
tcol.g = 255.0 - (((255.0 - tcol.g) * (255.0 - tint.g)) / 256.0);
tcol.r = 255.0 - (((255.0 - tcol.r) * (255.0 - tint.b)) / 256.0);
break;
case HICTINT_BLEND_OVERLAY:
case RF_HICTINT_BLEND_Overlay:
tcol.b = tcol.b < 128.0? (tcol.b * tint.r) / 128.0 : 255.0 - (((255.0 - tcol.b) * (255.0 - tint.r)) / 128.0);
tcol.g = tcol.g < 128.0? (tcol.g * tint.g) / 128.0 : 255.0 - (((255.0 - tcol.g) * (255.0 - tint.g)) / 128.0);
tcol.r = tcol.r < 128.0? (tcol.r * tint.b) / 128.0 : 255.0 - (((255.0 - tcol.r) * (255.0 - tint.b)) / 128.0);
break;
case HICTINT_BLEND_HARDLIGHT:
case RF_HICTINT_BLEND_Hardlight:
tcol.b = tint.r < 128.0 ? (tcol.b * tint.r) / 128.0 : 255.0 - (((255.0 - tcol.b) * (255.0 - r)) / 128.0);
tcol.g = tint.g < 128.0 ? (tcol.g * tint.g) / 128.0 : 255.0 - (((255.0 - tcol.g) * (255.0 - g)) / 128.0);
tcol.r = tint.b < 128.0 ? (tcol.r * tint.b) / 128.0 : 255.0 - (((255.0 - tcol.r) * (255.0 - b)) / 128.0);
@ -125,39 +133,38 @@ void main()
{
float fullbright = 0.0;
vec4 color;
if (u_useColorOnly == 0.0)
if ((u_flags & RF_ColorOnly) == 0)
{
float coordX = v_texCoord.x;
float coordY = v_texCoord.y;
vec2 newCoord;
// Coordinate adjustment for NPOT textures (something must have gone very wrong to make this necessary...)
if (u_npotEmulation != 0.0)
if ((u_flags & RF_NPOTEmulation) != 0)
{
float period = floor(coordY / u_npotEmulationFactor);
coordX += u_npotEmulationXOffset * floor(mod(coordY, u_npotEmulationFactor));
coordY = period + mod(coordY, u_npotEmulationFactor);
}
newCoord = vec2(coordX, coordY);
if (u_clamp != 0.0) newCoord = clamp(newCoord.xy, 0.0, 1.0);
// Paletted textures are stored in column major order rather than row major so coordinates need to be swapped here.
color = texture2D(s_texture, newCoord);
// This was further down but it really should be done before applying any kind of depth fading, not afterward.
vec4 detailColor = vec4(1.0);
if (u_useDetailMapping != 0.0)
if ((u_flags & RF_DetailMapping) != 0)
{
detailColor = texture2D(s_detail, v_detailCoord.xy);
detailColor = mix(vec4(1.0), 2.0 * detailColor, detailColor.a);
// Application of this differs based on render mode because for paletted rendering with palettized shade tables it can only be done after processing the shade table. We only have a palette index before.
}
float visibility = max(u_visFactor * v_distance - 0.5 * u_shadeInterpolate, 0.0);
float visibility = max(u_visFactor * v_distance - ((u_flags & RF_ShadeInterpolate) != 0.0? 0.5 : 0.0), 0.0);
float shade = clamp((u_shade + visibility), 0.0, u_numShades - 1.0);
if (u_usePalette != 0.0)
if ((u_flags & RF_UsePalette) != 0)
{
int palindex = int(color.r * 255.0 + 0.1); // The 0.1 is for roundoff error compensation.
int shadeindex = int(floor(shade));
@ -165,7 +172,7 @@ void main()
int colorIndex = int(colorIndexF * 255.0 + 0.1); // The 0.1 is for roundoff error compensation.
vec4 palettedColor = texelFetch(s_palette, ivec2(colorIndex, 0), 0);
if (u_shadeInterpolate != 0.0)
if ((u_flags & RF_ShadeInterpolate) != 0)
{
// Get the next shaded palette index for interpolation
colorIndexF = texelFetch(s_palswap, ivec2(palindex, shadeindex+1), 0).r;
@ -183,7 +190,7 @@ void main()
else
{
color.rgb *= detailColor.rgb;
if (u_fogColor.a == 0.0)
if ((u_flags & RF_FogDisabled) == 0)
{
shade = clamp(shade / (u_numShades-2), 0.0, 1.0);
// Apply the shade as a linear depth fade ramp.
@ -200,7 +207,7 @@ void main()
color = v_color;
}
if (u_useGlowMapping != 0.0 && u_useColorOnly == 0.0)
if ((u_flags & (RF_ColorOnly|RF_GlowMapping)) == RF_GlowMapping)
{
vec4 glowColor = texture2D(s_glow, v_texCoord.xy);
color.rgb = mix(color.rgb, glowColor.rgb, glowColor.a);