From 95b4340eec2dc26271217662fafeb6b6f2a786ae Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 15 Jun 2020 20:09:49 +0200 Subject: [PATCH] - initial palette shader work. --- source/glbackend/gl_palmanager.cpp | 60 +++++++---------- source/glbackend/gl_texture.cpp | 13 +--- source/glbackend/glbackend.cpp | 19 +++--- source/glbackend/glbackend.h | 31 ++------- source/glbackend/pm_renderstate.h | 1 - wadsrc/static/shaders/glsl/func_paletted.fp | 73 +++++++++++++++++++-- 6 files changed, 110 insertions(+), 87 deletions(-) diff --git a/source/glbackend/gl_palmanager.cpp b/source/glbackend/gl_palmanager.cpp index 79ee99ae1..dcbe10cbe 100644 --- a/source/glbackend/gl_palmanager.cpp +++ b/source/glbackend/gl_palmanager.cpp @@ -69,13 +69,11 @@ void PaletteManager::DeleteAll() if (pal) delete pal; pal = nullptr; } - for (auto& pal : palswaptextures) + for (auto& pal : lookuptextures) { if (pal) delete pal; pal = nullptr; } - lastindex = ~0u; - lastsindex = ~0u; } //=========================================================================== @@ -84,7 +82,7 @@ void PaletteManager::DeleteAll() // //=========================================================================== -void PaletteManager::BindPalette(int index) +IHardwareTexture *PaletteManager::GetPalette(int index) { auto palettedata = GPalette.GetTranslation(Translation_BasePalettes, index); if (palettedata == nullptr) @@ -95,20 +93,16 @@ void PaletteManager::BindPalette(int index) if (palettedata) { - if (index != lastindex) + if (palettetextures[index] == nullptr) { - lastindex = index; - - if (palettetextures[index] == nullptr) - { - auto p = screen->CreateHardwareTexture(4); - p->CreateTexture((uint8_t*)palettedata->Palette, 256, 1, 15, false, "Palette"); - palettetextures[index] = p; - } - inst->SetPaletteTexture(palettetextures[index]); + auto p = screen->CreateHardwareTexture(4); + p->CreateTexture((uint8_t*)palettedata->Palette, 256, 1, 15, false, "Palette"); + palettetextures[index] = p; } + return palettetextures[index]; } - + I_FatalError("palette not initialized for palette emulated render mode"); // we cannot continue if this happens. + return nullptr; } //=========================================================================== @@ -117,35 +111,31 @@ void PaletteManager::BindPalette(int index) // //=========================================================================== -void PaletteManager::BindPalswap(int index) +IHardwareTexture* PaletteManager::GetLookup(int index) { if (!lookups.checkTable(index)) index = 0; if (lookups.checkTable(index)) { - if (index != lastsindex) + if (lookuptextures[index] == nullptr) { - lastsindex = index; - if (palswaptextures[index] == nullptr) + auto p = screen->CreateHardwareTexture(1); + + // Perform a 0<->255 index swap. The lookup tables are still the original data. + TArray lookup(numshades * 256, true); + memcpy(lookup.Data(), lookups.getTable(index), lookup.Size()); + for (int i = 0; i < numshades; i++) { - auto p = screen->CreateHardwareTexture(1); - - // Perform a 0<->255 index swap. The lookup tables are still the original data. - TArray lookup(numshades * 256, true); - memcpy(lookup.Data(), lookups.getTable(index), lookup.Size()); - for (int i = 0; i < numshades; i++) - { - auto p = &lookup[i * 256]; - p[255] = p[0]; - p[0] = 0; - } - p->CreateTexture(lookup.Data(), 256, numshades, 15, false, "Palette"); - palswaptextures[index] = p; + auto p = &lookup[i * 256]; + p[255] = p[0]; + p[0] = 0; } - inst->SetLookupTexture(palswaptextures[index]); - inst->SetFadeColor(lookups.getFade(index)); + p->CreateTexture(lookup.Data(), 256, numshades, 15, false, "PaletteLookup"); + lookuptextures[index] = p; } + return lookuptextures[index]; } - + I_FatalError("palette lookups not initialized for palette emulated render mode"); // we cannot continue if this happens. + return nullptr; } diff --git a/source/glbackend/gl_texture.cpp b/source/glbackend/gl_texture.cpp index 86176ab0a..a5744c7fb 100644 --- a/source/glbackend/gl_texture.cpp +++ b/source/glbackend/gl_texture.cpp @@ -64,17 +64,8 @@ bool GLInstance::SetTexture(int picnum, FGameTexture* tex, int paletteid, int sa // This is intentionally the same value for both parameters. The shader does not use the same uniform for modulation and overlay colors. SetTinting(texpick.tintFlags, texpick.tintColor, texpick.tintColor); - if (texpick.translation != 0) - { - int lookuppal = texpick.translation & 0x7fffffff; - SetPalette(GetTranslationType(lookuppal) - Translation_Remap); - SetPalswap(GetTranslationIndex(lookuppal)); - } - else - { - SetPalette(0); - SetPalswap(0); - } + int lookuppal = texpick.translation & 0x7fffffff; + SetPalswap(GetTranslationIndex(lookuppal)); SetBasepalTint(texpick.basepalTint); auto &mat = renderState.mMaterial; diff --git a/source/glbackend/glbackend.cpp b/source/glbackend/glbackend.cpp index 26670fb0d..9401b4786 100644 --- a/source/glbackend/glbackend.cpp +++ b/source/glbackend/glbackend.cpp @@ -78,8 +78,18 @@ GLInstance::GLInstance() //ImGuiContext* im_ctx; TArray ttf; +IHardwareTexture *setpalettelayer(int layer, int translation) +{ + if (layer == 1) + return GLInterface.palmanager.GetPalette(GetTranslationType(translation) - Translation_Remap); + else if (layer == 2) + return GLInterface.palmanager.GetLookup(GetTranslationIndex(translation)); + else return nullptr; +} + void GLInstance::Init(int ydim) { + FMaterial::SetLayerCallback(setpalettelayer); new(&renderState) PolymostRenderState; // reset to defaults. } @@ -143,17 +153,10 @@ void GLInstance::SetIdentityMatrix(int num) renderState.matrixIndex[num] = -1; } - -void GLInstance::SetPalette(int index) -{ - palmanager.BindPalette(index); -} - - void GLInstance::SetPalswap(int index) { - palmanager.BindPalswap(index); renderState.ShadeDiv = lookups.tables[index].ShadeFactor; + renderState.FogColor = lookups.getFade(index); } void PolymostRenderState::Apply(FRenderState& state, GLState& oldState) diff --git a/source/glbackend/glbackend.h b/source/glbackend/glbackend.h index 9332b1b32..c2073f874 100644 --- a/source/glbackend/glbackend.h +++ b/source/glbackend/glbackend.h @@ -29,10 +29,7 @@ enum class PaletteManager { IHardwareTexture* palettetextures[256] = {}; - IHardwareTexture* palswaptextures[256] = {}; - - uint32_t lastindex = ~0u; - uint32_t lastsindex = ~0u; + IHardwareTexture* lookuptextures[256] = {}; GLInstance* const inst; @@ -43,8 +40,8 @@ public: {} ~PaletteManager(); void DeleteAll(); - void BindPalette(int index); - void BindPalswap(int index); + IHardwareTexture *GetPalette(int index); + IHardwareTexture* GetLookup(int index); }; @@ -80,6 +77,8 @@ struct GLState class GLInstance { + friend IHardwareTexture* setpalettelayer(int layer, int translation); + public: TArray rendercommands; PaletteManager palmanager; @@ -121,8 +120,6 @@ public: renderState.matrixIndex[num] = index; } - void SetPalette(int palette); - void SetTextureMode(int m) { renderState.TextureMode = m; @@ -307,11 +304,6 @@ public: else renderState.Flags &= ~RF_ShadeInterpolate; } - void SetFadeColor(PalEntry color) - { - renderState.FogColor = color; - }; - void SetFadeDisable(bool yes) { if (yes) renderState.Flags |= RF_FogDisabled; @@ -359,20 +351,7 @@ public: renderState.AlphaThreshold = al; } - void SetPaletteTexture(IHardwareTexture* tex) - { - renderState.PaletteTexture = tex; - } - - void SetLookupTexture(IHardwareTexture* tex) - { - renderState.LookupTexture = tex; - } - bool SetTexture(int globalpicnum, FGameTexture* tex, int palette, int sampleroverride); - void RenderScene(FRenderState& state); - void DrawScene(int drawmode); - }; extern GLInstance GLInterface; diff --git a/source/glbackend/pm_renderstate.h b/source/glbackend/pm_renderstate.h index c0751cd2c..a30c35d52 100644 --- a/source/glbackend/pm_renderstate.h +++ b/source/glbackend/pm_renderstate.h @@ -61,7 +61,6 @@ struct PolymostRenderState int hictint_flags = -1; FDepthBiasState mBias{ }; FMaterialState mMaterial; - IHardwareTexture* PaletteTexture = nullptr, * LookupTexture = nullptr; int StateFlags = STF_COLORMASK|STF_DEPTHMASK; FRenderStyle Style{}; diff --git a/wadsrc/static/shaders/glsl/func_paletted.fp b/wadsrc/static/shaders/glsl/func_paletted.fp index fbcd99234..53b97b7b3 100644 --- a/wadsrc/static/shaders/glsl/func_paletted.fp +++ b/wadsrc/static/shaders/glsl/func_paletted.fp @@ -1,10 +1,71 @@ +const int RF_ShadeInterpolate = 64; + +//=========================================================================== +// +// +// +//=========================================================================== + vec4 ProcessTexel() { - float index = getTexel(vTexCoord.st).r; - index = ((index * 255.0) + 0.5) / 256.0; - vec4 tex = texture(texture2, vec2(index, 0.5)); - tex.a = 1.0; - return tex; -} + int u_flags = RF_ShadeInterpolate; + float fullbright = 0.0; + vec4 color; + float coordX = vTexCoord.x; + float coordY = vTexCoord.y; + vec2 newCoord; + + // z is the depth in view space, positive going into the screen + float z; + if (((uPalLightLevels >> 8) & 0xff) == 2) + { + z = distance(pixelpos.xyz, uCameraPos.xyz); + } + else + { + z = pixelpos.w; + } + + // Coordinate adjustment for NPOT textures. It is somehow fitting that Build games exploited this texture wrapping quirk of the software rendering engine... + if (uNpotEmulation.y != 0.0) + { + float period = floor(coordY / uNpotEmulation.y); + coordX += uNpotEmulation.x * floor(mod(coordY, uNpotEmulation.y)); + coordY = period + mod(coordY, uNpotEmulation.y); + } + newCoord = vec2(coordX, coordY); + color = texture(tex, newCoord); + + float visibility = max(uGlobVis * uLightFactor * z - ((u_flags & RF_ShadeInterpolate) != 0.0? 0.5 : 0.0), 0.0); + float numShades = float(uPalLightLevels & 255); + float shade = clamp((uLightLevel + visibility), 0.0, numShades - 1.0); + + int palindex = int(color.r * 255.0 + 0.1); // The 0.1 is for roundoff error compensation. + int shadeindex = int(floor(shade)); + float colorIndexF = texelFetch(texture3, ivec2(palindex, shadeindex), 0).r; + int colorIndex = int(colorIndexF * 255.0 + 0.1); // The 0.1 is for roundoff error compensation. + vec4 palettedColor = texelFetch(texture2, ivec2(colorIndex, 0), 0); + + if ((u_flags & RF_ShadeInterpolate) != 0) + { + // Get the next shaded palette index for interpolation + colorIndexF = texelFetch(texture3, ivec2(palindex, shadeindex+1), 0).r; + colorIndex = int(colorIndexF * 255.0 + 0.1); // The 0.1 is for roundoff error compensation. + vec4 palettedColorNext = texelFetch(texture2, ivec2(colorIndex, 0), 0); + float shadeFrac = mod(shade, 1.0); + palettedColor.rgb = mix(palettedColor.rgb, palettedColorNext.rgb, shadeFrac); + } + + palettedColor.a = color.r == 0.0? 0.0 : 1.0;// 1.0-floor(color.r); + color = palettedColor; + + if (uFogDensity != 0.0) // fog hack for RRRA E2L1. Needs to be done better, this is gross, but still preferable to the broken original implementation. + { + float fogfactor = 0.55 + 0.3 * exp2 (uFogDensity * abs(z) / 1024.0); + color.rgb = uFogColor.rgb * (1.0-fogfactor) + color.rgb * fogfactor;// mix(vec3(0.6), color.rgb, fogfactor); + } + if (color.a < uAlphaThreshold) discard; // it's only here that we have the alpha value available to be able to perform the alpha test. + return color; +}