- 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 polymost_outputGLDebugMessage(uint8_t severity, const char* format, ...);
//void phex(char v, char *s); //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 uploadpalswaps(int count, int32_t *palookupnum);
void polymost_drawsprite(int32_t snum); void polymost_drawsprite(int32_t snum);
void polymost_drawmaskwall(int32_t damaskwallcnt); 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 #ifdef USE_OPENGL
if (videoGetRenderMode() >= REND_POLYMOST) if (videoGetRenderMode() >= REND_POLYMOST)
{ {
uploadbasepalette(id, transient); uploadbasepalette(id);
} }
#endif #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]) if (!basepaltable[basepalnum])
{ {
@ -382,7 +382,7 @@ void uploadbasepalette(int32_t basepalnum, bool transient) // transient palettes
basepalWFullBrightInfo[i*4+3] = 0-(IsPaletteIndexFullbright(i) != 0); 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. // 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 (pal.swaptexture) delete pal.swaptexture;
} }
if (transientpalette.paltexture) delete transientpalette.paltexture;
if (palswapTexture) delete palswapTexture; if (palswapTexture) delete palswapTexture;
palswapTexture = nullptr; palswapTexture = nullptr;
transientpalette.paltexture = nullptr;
transientpalette.crc32 = -1;
palettes.Reset(); palettes.Reset();
palswaps.Reset(); palswaps.Reset();
lastindex = ~0u; 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. // 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. // 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 (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); palettemap[index] = FindPalette(data);
if (index == 0) if (index == 0)
{ {
@ -203,19 +186,7 @@ void PaletteManager::SetPalette(int index, const uint8_t* data, bool transient)
void PaletteManager::BindPalette(int index) void PaletteManager::BindPalette(int index)
{ {
if (index == transientpalette.crc32) if (palettemap[index] < palettes.Size())
{
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())
{ {
auto uindex = palettemap[index]; auto uindex = palettemap[index];
if (uindex != lastindex) if (uindex != lastindex)

View file

@ -1,23 +1,38 @@
#pragma once #pragma once
#include "PalEntry.h"
class PolymostShader; 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 struct PolymostRenderState
{ {
float Clamp[2];
float Shade; float Shade;
float NumShades = 64.f; float NumShades = 64.f;
float VisFactor = 128.f; float VisFactor = 128.f;
float UseColorOnly; int Flags = 0;
float UsePalette = 1.f;
float UseDetailMapping;
float UseGlowMapping;
float NPOTEmulation;
float NPOTEmulationFactor = 1.f; float NPOTEmulationFactor = 1.f;
float NPOTEmulationXOffset; float NPOTEmulationXOffset;
float Brightness = 1.f; float Brightness = 1.f;
float ShadeInterpolate = 1.f; PalEntry FogColor;
float FogColor[4];
void Apply(PolymostShader *shader); 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; 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"); Shade.Init(hShader, "u_shade");
NumShades.Init(hShader, "u_numShades"); NumShades.Init(hShader, "u_numShades");
VisFactor.Init(hShader, "u_visFactor"); 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"); NPOTEmulationFactor.Init(hShader, "u_npotEmulationFactor");
NPOTEmulationXOffset.Init(hShader, "u_npotEmulationXOffset"); NPOTEmulationXOffset.Init(hShader, "u_npotEmulationXOffset");
Brightness.Init(hShader, "u_brightness"); Brightness.Init(hShader, "u_brightness");
ShadeInterpolate.Init(hShader, "u_shadeInterpolate");
FogColor.Init(hShader, "u_fogColor"); FogColor.Init(hShader, "u_fogColor");
RotMatrix.Init(hShader, "u_rotMatrix"); RotMatrix.Init(hShader, "u_rotMatrix");

View file

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

View file

@ -1,5 +1,28 @@
#pragma once #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 class FBufferedUniform1f
{ {
float mBuffer; 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 class FUniformMatrix4f
{ {
int mIndex; int mIndex;

View file

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

View file

@ -55,10 +55,6 @@ class PaletteManager
uint32_t lastsindex = ~0u; uint32_t lastsindex = ~0u;
int numshades = 1; 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. // All data is being stored in contiguous blocks that can be used as uniform buffers as-is.
TArray<PaletteData> palettes; TArray<PaletteData> palettes;
TArray<PalswapData> palswaps; TArray<PalswapData> palswaps;
@ -76,7 +72,7 @@ public:
{} {}
~PaletteManager(); ~PaletteManager();
void DeleteAll(); 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 SetPalswapData(int index, const uint8_t* data, int numshades);
void BindPalette(int index); void BindPalette(int index);
@ -278,8 +274,6 @@ public:
} }
void SetDepthFunc(int func); void SetDepthFunc(int func);
void SetFadeColor(PalEntry color);
void SetFadeDisable(bool on);
void SetColorMask(bool on); void SetColorMask(bool on);
void SetDepthMask(bool on); void SetDepthMask(bool on);
void SetBlendFunc(int src, int dst); void SetBlendFunc(int src, int dst);
@ -298,9 +292,9 @@ public:
void ReadPixels(int w, int h, uint8_t* buffer); 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) void SetPalswapData(int index, const uint8_t* data, int numshades)
@ -312,13 +306,14 @@ public:
int GetClamp() 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) void SetClamp(int clamp)
{ {
renderState.Clamp[0] = clamp & 1; // This option is totally pointless and should be removed.
renderState.Clamp[1] = !!(clamp & 2); //renderState.Clamp[0] = clamp & 1;
//renderState.Clamp[1] = !!(clamp & 2);
} }
void SetShade(int32_t shade, int numshades) void SetShade(int32_t shade, int numshades)
@ -332,31 +327,56 @@ public:
renderState.VisFactor = visibility * fviewingrange * (1.f / (64.f * 65536.f)); 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.NPOTEmulationFactor = factor;
renderState.NPOTEmulationXOffset = xOffset; 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) void SetBrightness(int brightness)

View file

@ -1,5 +1,23 @@
#version 330 #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 //s_texture points to an indexed color texture
uniform sampler2D s_texture; uniform sampler2D s_texture;
//s_palswap is the palette swap texture where u is the color index and v is the shade //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_detail;
uniform sampler2D s_glow; uniform sampler2D s_glow;
uniform vec2 u_clamp;
uniform float u_shade; uniform float u_shade;
uniform float u_numShades; uniform float u_numShades;
uniform float u_visFactor; 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_npotEmulationFactor;
uniform float u_npotEmulationXOffset; uniform float u_npotEmulationXOffset;
uniform float u_shadeInterpolate;
uniform float u_brightness; uniform float u_brightness;
uniform vec4 u_fogColor; uniform vec4 u_fogColor;
uniform float u_useDetailMapping;
uniform float u_useGlowMapping;
uniform int u_tinteffect;
uniform vec3 u_tintcolor; uniform vec3 u_tintcolor;
uniform vec3 u_tintmodulate;
in vec4 v_color; in vec4 v_color;
in float v_distance; in float v_distance;
@ -71,13 +79,13 @@ vec4 convertColor(vec4 color, int effect, vec3 tint)
{ {
#if 0 #if 0
if (effect & HICTINT_GRAYSCALE) if (effect & RF_HICTINT_Grayscale)
{ {
float g = grayscale(color); float g = grayscale(color);
color = vec4(g, g, g, color.a); 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); 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. vec3 tcol = color.rgb * 255.0; // * 255.0 to make it easier to reuse the integer math.
tint *= 255.0; tint *= 255.0;
if (effect & HICTINT_COLORIZE) if (effect & RF_HICTINT_Colorize)
{ {
tcol.b = min(((tcol.b) * tint.r) / 64.0, 255.0); tcol.b = min(((tcol.b) * tint.r) / 64.0, 255.0);
tcol.g = min(((tcol.g) * tint.g) / 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); 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.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.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); tcol.r = 255.0 - (((255.0 - tcol.r) * (255.0 - tint.b)) / 256.0);
break; 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.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.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); 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; 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.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.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); 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; float fullbright = 0.0;
vec4 color; vec4 color;
if (u_useColorOnly == 0.0) if ((u_flags & RF_ColorOnly) == 0)
{ {
float coordX = v_texCoord.x; float coordX = v_texCoord.x;
float coordY = v_texCoord.y; float coordY = v_texCoord.y;
vec2 newCoord; vec2 newCoord;
// Coordinate adjustment for NPOT textures (something must have gone very wrong to make this necessary...) // 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); float period = floor(coordY / u_npotEmulationFactor);
coordX += u_npotEmulationXOffset * floor(mod(coordY, u_npotEmulationFactor)); coordX += u_npotEmulationXOffset * floor(mod(coordY, u_npotEmulationFactor));
coordY = period + mod(coordY, u_npotEmulationFactor); coordY = period + mod(coordY, u_npotEmulationFactor);
} }
newCoord = vec2(coordX, coordY); 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. // Paletted textures are stored in column major order rather than row major so coordinates need to be swapped here.
color = texture2D(s_texture, newCoord); color = texture2D(s_texture, newCoord);
// This was further down but it really should be done before applying any kind of depth fading, not afterward. // This was further down but it really should be done before applying any kind of depth fading, not afterward.
vec4 detailColor = vec4(1.0); vec4 detailColor = vec4(1.0);
if (u_useDetailMapping != 0.0) if ((u_flags & RF_DetailMapping) != 0)
{ {
detailColor = texture2D(s_detail, v_detailCoord.xy); detailColor = texture2D(s_detail, v_detailCoord.xy);
detailColor = mix(vec4(1.0), 2.0 * detailColor, detailColor.a); 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. // 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); 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 palindex = int(color.r * 255.0 + 0.1); // The 0.1 is for roundoff error compensation.
int shadeindex = int(floor(shade)); 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. 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); 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 // Get the next shaded palette index for interpolation
colorIndexF = texelFetch(s_palswap, ivec2(palindex, shadeindex+1), 0).r; colorIndexF = texelFetch(s_palswap, ivec2(palindex, shadeindex+1), 0).r;
@ -183,7 +190,7 @@ void main()
else else
{ {
color.rgb *= detailColor.rgb; 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); shade = clamp(shade / (u_numShades-2), 0.0, 1.0);
// Apply the shade as a linear depth fade ramp. // Apply the shade as a linear depth fade ramp.
@ -200,7 +207,7 @@ void main()
color = v_color; 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); vec4 glowColor = texture2D(s_glow, v_texCoord.xy);
color.rgb = mix(color.rgb, glowColor.rgb, glowColor.a); color.rgb = mix(color.rgb, glowColor.rgb, glowColor.a);