diff --git a/source/build/include/polymost.h b/source/build/include/polymost.h index 0eeffbf35..2be804aca 100644 --- a/source/build/include/polymost.h +++ b/source/build/include/polymost.h @@ -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); diff --git a/source/build/src/palette.cpp b/source/build/src/palette.cpp index 0ad784c47..35c47328c 100644 --- a/source/build/src/palette.cpp +++ b/source/build/src/palette.cpp @@ -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 } diff --git a/source/build/src/polymost.cpp b/source/build/src/polymost.cpp index 0bc4917d9..87467ac80 100644 --- a/source/build/src/polymost.cpp +++ b/source/build/src/polymost.cpp @@ -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. diff --git a/source/glbackend/gl_palmanager.cpp b/source/glbackend/gl_palmanager.cpp index 725420290..5a25e643b 100644 --- a/source/glbackend/gl_palmanager.cpp +++ b/source/glbackend/gl_palmanager.cpp @@ -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) diff --git a/source/glbackend/gl_renderstate.h b/source/glbackend/gl_renderstate.h index 2e7c525b4..bd91abc2c 100644 --- a/source/glbackend/gl_renderstate.h +++ b/source/glbackend/gl_renderstate.h @@ -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); }; diff --git a/source/glbackend/gl_shader.cpp b/source/glbackend/gl_shader.cpp index bcb06e8a5..d78796576 100644 --- a/source/glbackend/gl_shader.cpp +++ b/source/glbackend/gl_shader.cpp @@ -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"); - Shade.Init(hShader, "u_shade"); + 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"); diff --git a/source/glbackend/gl_shader.h b/source/glbackend/gl_shader.h index fadc13d86..13f7b89d6 100644 --- a/source/glbackend/gl_shader.h +++ b/source/glbackend/gl_shader.h @@ -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; diff --git a/source/glbackend/gl_uniform.h b/source/glbackend/gl_uniform.h index 1fdc722fe..ff53d7adf 100644 --- a/source/glbackend/gl_uniform.h +++ b/source/glbackend/gl_uniform.h @@ -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; diff --git a/source/glbackend/glbackend.cpp b/source/glbackend/glbackend.cpp index 508ca7358..10f309454 100644 --- a/source/glbackend/glbackend.cpp +++ b/source/glbackend/glbackend.cpp @@ -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); diff --git a/source/glbackend/glbackend.h b/source/glbackend/glbackend.h index c9dc3e2b9..d659a5ef3 100644 --- a/source/glbackend/glbackend.h +++ b/source/glbackend/glbackend.h @@ -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 palettes; TArray 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; - renderState.NPOTEmulationFactor = factor; - renderState.NPOTEmulationXOffset = xOffset; + if (yes) renderState.Flags |= RF_Brightmapping; + else renderState.Flags &= ~RF_Brightmapping; } - void SetShadeInterpolate(int32_t shadeInterpolate) + void SetNpotEmulation(bool yes, float factor, float xOffset) { - renderState.ShadeInterpolate = shadeInterpolate; + if (yes) + { + renderState.Flags |= RF_NPOTEmulation; + renderState.NPOTEmulationFactor = factor; + renderState.NPOTEmulationXOffset = xOffset; + } + else renderState.Flags &= ~RF_NPOTEmulation; + } + + void SetShadeInterpolate(int32_t yes) + { + 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) diff --git a/wadsrc/static/demolition/shaders/glsl/polymost.fp b/wadsrc/static/demolition/shaders/glsl/polymost.fp index 1259d5f9e..fed1f0c61 100644 --- a/wadsrc/static/demolition/shaders/glsl/polymost.fp +++ b/wadsrc/static/demolition/shaders/glsl/polymost.fp @@ -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);