From acf6c259d84d3c7670d6bcf81bfd29a37b8efb27 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 9 Sep 2014 13:21:36 +0200 Subject: [PATCH] - changed the handling of alpha textures. The only special case they need is with palette-less textures and this can be handled far more easily and robustly with a predefined translation instead of passing another parameter through all the layers of the texture management code. This also fixes problems with paletted PNGs that get used as an alpha texture because the old method clobbered the image's palette. --- src/gl/renderer/gl_lightdata.cpp | 6 +++++- src/gl/renderer/gl_renderstate.h | 10 ++++++++- src/gl/system/gl_interface.h | 7 ++++--- src/gl/system/gl_wipe.cpp | 22 ++++++++++---------- src/gl/textures/gl_bitmap.cpp | 19 ++++------------- src/gl/textures/gl_bitmap.h | 11 +--------- src/gl/textures/gl_hwtexture.cpp | 17 +++------------ src/gl/textures/gl_hwtexture.h | 10 ++------- src/gl/textures/gl_material.cpp | 33 +++++++++++++----------------- src/gl/textures/gl_material.h | 14 ++++++------- src/r_data/r_translate.cpp | 9 ++++++++ wadsrc/static/shaders/glsl/main.fp | 10 ++++++--- 12 files changed, 75 insertions(+), 93 deletions(-) diff --git a/src/gl/renderer/gl_lightdata.cpp b/src/gl/renderer/gl_lightdata.cpp index 29013f2809..a02762eb80 100644 --- a/src/gl/renderer/gl_lightdata.cpp +++ b/src/gl/renderer/gl_lightdata.cpp @@ -142,7 +142,11 @@ void gl_GetRenderStyle(FRenderStyle style, bool drawopaque, bool allowcolorblend int blendequation = renderops[style.BlendOp&15]; int texturemode = drawopaque? TM_OPAQUE : TM_MODULATE; - if (style.Flags & STYLEF_ColorIsFixed) + if (style.Flags & STYLEF_RedIsAlpha) + { + texturemode = TM_REDTOALPHA; + } + else if (style.Flags & STYLEF_ColorIsFixed) { texturemode = TM_MASK; } diff --git a/src/gl/renderer/gl_renderstate.h b/src/gl/renderer/gl_renderstate.h index 236b5d5515..e0f5406ddb 100644 --- a/src/gl/renderer/gl_renderstate.h +++ b/src/gl/renderer/gl_renderstate.h @@ -8,6 +8,7 @@ #include "gl/textures/gl_material.h" #include "c_cvars.h" #include "r_defs.h" +#include "r_data/r_translate.h" class FVertexBuffer; class FShader; @@ -100,9 +101,16 @@ public: void SetMaterial(FMaterial *mat, int clampmode, int translation, int overrideshader, bool alphatexture) { + // textures without their own palette are a special case for use as an alpha texture: + // They use the color index directly as an alpha value instead of using the palette's red. + // To handle this case, we need to set a special translation for such textures. + if (alphatexture) + { + if (mat->tex->UseBasePalette()) translation = TRANSLATION(TRANSLATION_Standard, 8); + } mEffectState = overrideshader >= 0? overrideshader : mat->mShaderIndex; mShaderTimer = mat->tex->gl_info.shaderspeed; - mat->Bind(clampmode, translation, alphatexture); + mat->Bind(clampmode, translation); } void Apply(); diff --git a/src/gl/system/gl_interface.h b/src/gl/system/gl_interface.h index af4c4f7c2d..2d2e26d514 100644 --- a/src/gl/system/gl_interface.h +++ b/src/gl/system/gl_interface.h @@ -16,9 +16,10 @@ enum RenderFlags enum TexMode { TM_MODULATE = 0, // (r, g, b, a) - TM_MASK = 1, // (1, 1, 1, a) - TM_OPAQUE = 2, // (r, g, b, 1) - TM_INVERSE = 3, // (1-r, 1-g, 1-b, a) + TM_MASK, // (1, 1, 1, a) + TM_OPAQUE, // (r, g, b, 1) + TM_INVERSE, // (1-r, 1-g, 1-b, a) + TM_REDTOALPHA, // (1, 1, 1, r) }; struct RenderContext diff --git a/src/gl/system/gl_wipe.cpp b/src/gl/system/gl_wipe.cpp index 564dd1e032..30a9968165 100644 --- a/src/gl/system/gl_wipe.cpp +++ b/src/gl/system/gl_wipe.cpp @@ -148,11 +148,11 @@ bool OpenGLFrameBuffer::WipeStartScreen(int type) } wipestartscreen = new FHardwareTexture(Width, Height, true); - wipestartscreen->CreateTexture(NULL, Width, Height, 0, false, 0, false); + wipestartscreen->CreateTexture(NULL, Width, Height, 0, false, 0); GLRenderer->mSamplerManager->Bind(0, CLAMP_NOFILTER); GLRenderer->mSamplerManager->Bind(1, CLAMP_NONE); glFinish(); - wipestartscreen->Bind(0, false, false, false); + wipestartscreen->Bind(0, false, false); glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, Width, Height); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); @@ -171,10 +171,10 @@ bool OpenGLFrameBuffer::WipeStartScreen(int type) void OpenGLFrameBuffer::WipeEndScreen() { wipeendscreen = new FHardwareTexture(Width, Height, true); - wipeendscreen->CreateTexture(NULL, Width, Height, 0, false, 0, false); + wipeendscreen->CreateTexture(NULL, Width, Height, 0, false, 0); GLRenderer->mSamplerManager->Bind(0, CLAMP_NOFILTER); glFinish(); - wipeendscreen->Bind(0, false, false, false); + wipeendscreen->Bind(0, false, false); glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, Width, Height); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); @@ -286,7 +286,7 @@ bool OpenGLFrameBuffer::Wiper_Crossfade::Run(int ticks, OpenGLFrameBuffer *fb) gl_RenderState.AlphaFunc(GL_GEQUAL, 0.f); gl_RenderState.ResetColor(); gl_RenderState.Apply(); - fb->wipestartscreen->Bind(0, 0, false, false); + fb->wipestartscreen->Bind(0, 0, false); FFlatVertex *ptr; unsigned int offset, count; @@ -301,7 +301,7 @@ bool OpenGLFrameBuffer::Wiper_Crossfade::Run(int ticks, OpenGLFrameBuffer *fb) ptr++; GLRenderer->mVBO->RenderCurrent(ptr, GL_TRIANGLE_STRIP, &offset, &count); - fb->wipeendscreen->Bind(0, 0, false, false); + fb->wipeendscreen->Bind(0, 0, false); gl_RenderState.SetColorAlpha(0xffffff, clamp(Clock/32.f, 0.f, 1.f)); gl_RenderState.Apply(); GLRenderer->mVBO->RenderArray(GL_TRIANGLE_STRIP, offset, count); @@ -348,7 +348,7 @@ bool OpenGLFrameBuffer::Wiper_Melt::Run(int ticks, OpenGLFrameBuffer *fb) gl_RenderState.SetTextureMode(TM_OPAQUE); gl_RenderState.ResetColor(); gl_RenderState.Apply(); - fb->wipeendscreen->Bind(0, 0, false, false); + fb->wipeendscreen->Bind(0, 0, false); FFlatVertex *ptr; ptr = GLRenderer->mVBO->GetBuffer(); ptr->Set(0, 0, 0, 0, vb); @@ -364,7 +364,7 @@ bool OpenGLFrameBuffer::Wiper_Melt::Run(int ticks, OpenGLFrameBuffer *fb) int i, dy; bool done = false; - fb->wipestartscreen->Bind(0, 0, false, false); + fb->wipestartscreen->Bind(0, 0, false); // Copy the old screen in vertical strips on top of the new one. while (ticks--) { @@ -496,7 +496,7 @@ bool OpenGLFrameBuffer::Wiper_Burn::Run(int ticks, OpenGLFrameBuffer *fb) gl_RenderState.AlphaFunc(GL_GEQUAL, 0.f); gl_RenderState.ResetColor(); gl_RenderState.Apply(); - fb->wipestartscreen->Bind(0, 0, false, false); + fb->wipestartscreen->Bind(0, 0, false); FFlatVertex *ptr; unsigned int offset, count; ptr = GLRenderer->mVBO->GetBuffer(); @@ -516,9 +516,9 @@ bool OpenGLFrameBuffer::Wiper_Burn::Run(int ticks, OpenGLFrameBuffer *fb) gl_RenderState.Apply(); // Burn the new screen on top of it. - fb->wipeendscreen->Bind(0, 0, false, false); + fb->wipeendscreen->Bind(0, 0, false); - BurnTexture->CreateTexture(rgb_buffer, WIDTH, HEIGHT, 1, true, 0, false); + BurnTexture->CreateTexture(rgb_buffer, WIDTH, HEIGHT, 1, true, 0); GLRenderer->mVBO->RenderArray(GL_TRIANGLE_STRIP, offset, count); gl_RenderState.SetEffect(EFF_NONE); diff --git a/src/gl/textures/gl_bitmap.cpp b/src/gl/textures/gl_bitmap.cpp index 0c74c9ae70..a2319f67c4 100644 --- a/src/gl/textures/gl_bitmap.cpp +++ b/src/gl/textures/gl_bitmap.cpp @@ -51,7 +51,7 @@ // //=========================================================================== template -void iCopyColors(unsigned char * pout, const unsigned char * pin, bool alphatex, int count, int step) +void iCopyColors(unsigned char * pout, const unsigned char * pin, int count, int step) { int i; @@ -69,7 +69,7 @@ void iCopyColors(unsigned char * pout, const unsigned char * pin, bool alphatex, } } -typedef void (*CopyFunc)(unsigned char * pout, const unsigned char * pin, bool alphatex, int count, int step); +typedef void (*CopyFunc)(unsigned char * pout, const unsigned char * pin, int count, int step); static CopyFunc copyfuncs[]={ iCopyColors, @@ -99,7 +99,7 @@ void FGLBitmap::CopyPixelDataRGB(int originx, int originy, BYTE *buffer = GetPixels() + 4*originx + Pitch*originy; for (int y=0;y 0) + if (translation > 0) { PalEntry *ptrans = GLTranslationPalette::GetPalette(translation); if (ptrans) diff --git a/src/gl/textures/gl_bitmap.h b/src/gl/textures/gl_bitmap.h index 98addb51dc..6aea6d0080 100644 --- a/src/gl/textures/gl_bitmap.h +++ b/src/gl/textures/gl_bitmap.h @@ -7,34 +7,25 @@ class FGLBitmap : public FBitmap { - bool alphatex; int translation; public: FGLBitmap() { - alphatex = false; translation = 0; } FGLBitmap(BYTE *buffer, int pitch, int width, int height) : FBitmap(buffer, pitch, width, height) { - alphatex = false; translation = 0; } void SetTranslationInfo(int _trans) { - if (_trans == -1) alphatex = true; - else if (_trans != -1337) translation = _trans; + if (_trans != -1337) translation = _trans; } - void SetAlphaTex() - { - alphatex = true; - } - virtual void CopyPixelDataRGB(int originx, int originy, const BYTE *patch, int srcwidth, int srcheight, int step_x, int step_y, int rotate, int ct, FCopyInfo *inf = NULL); virtual void CopyPixelData(int originx, int originy, const BYTE * patch, int srcwidth, int srcheight, diff --git a/src/gl/textures/gl_hwtexture.cpp b/src/gl/textures/gl_hwtexture.cpp index f491169b41..c855ef2855 100644 --- a/src/gl/textures/gl_hwtexture.cpp +++ b/src/gl/textures/gl_hwtexture.cpp @@ -184,18 +184,13 @@ void FHardwareTexture::Resize(int width, int height, unsigned char *src_data, un // //=========================================================================== -unsigned int FHardwareTexture::CreateTexture(unsigned char * buffer, int w, int h, int texunit, bool mipmap, int translation, bool alphatexture) +unsigned int FHardwareTexture::CreateTexture(unsigned char * buffer, int w, int h, int texunit, bool mipmap, int translation) { int rh,rw; int texformat=TexFormat[gl_texture_format]; bool deletebuffer=false; - if (alphatexture) - { - texformat = GL_R8; - translation = TRANS_Alpha; - } - else if (forcenocompression) + if (forcenocompression) { texformat = GL_RGBA8; } @@ -245,11 +240,6 @@ unsigned int FHardwareTexture::CreateTexture(unsigned char * buffer, int w, int glTex->mipmapped = true; } - if (alphatexture) - { - static const GLint swizzleMask[] = {GL_ONE, GL_ONE, GL_ONE, GL_RED}; - glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); - } if (texunit != 0) glActiveTexture(GL_TEXTURE0); return glTex->glTexID; } @@ -362,9 +352,8 @@ FHardwareTexture::TranslatedTexture *FHardwareTexture::GetTexID(int translation) // Binds this patch // //=========================================================================== -unsigned int FHardwareTexture::Bind(int texunit, int translation, bool alphatexture, bool needmipmap) +unsigned int FHardwareTexture::Bind(int texunit, int translation, bool needmipmap) { - if (alphatexture) translation = TRANS_Alpha; TranslatedTexture *pTex = GetTexID(translation); if (pTex->glTexID != 0) diff --git a/src/gl/textures/gl_hwtexture.h b/src/gl/textures/gl_hwtexture.h index eabc7a6efe..7fa0f05808 100644 --- a/src/gl/textures/gl_hwtexture.h +++ b/src/gl/textures/gl_hwtexture.h @@ -20,11 +20,6 @@ enum EInvalid Invalid = 0 }; -enum ETranslation -{ - TRANS_Alpha = INT_MAX -}; - enum { GLT_CLAMPX=1, @@ -66,7 +61,6 @@ private: TArray glTex_Translated; unsigned int glDepthID; // only used by camera textures - void LoadImage(unsigned char * buffer,int w, int h, TranslatedTexture *glTex, bool mipmap, bool alphatexture, int texunit); TranslatedTexture * GetTexID(int translation); int GetDepthBuffer(); @@ -81,8 +75,8 @@ public: void BindToFrameBuffer(); - unsigned int Bind(int texunit, int translation, bool alphatexture, bool needmipmap); - unsigned int CreateTexture(unsigned char * buffer, int w, int h, int texunit, bool mipmap, int translation, bool alphatexture); + unsigned int Bind(int texunit, int translation, bool needmipmap); + unsigned int CreateTexture(unsigned char * buffer, int w, int h, int texunit, bool mipmap, int translation); void Clean(bool all); }; diff --git a/src/gl/textures/gl_material.cpp b/src/gl/textures/gl_material.cpp index 063f948c04..6b22e0a5e6 100644 --- a/src/gl/textures/gl_material.cpp +++ b/src/gl/textures/gl_material.cpp @@ -109,7 +109,7 @@ FGLTexture::~FGLTexture() // Checks for the presence of a hires texture replacement and loads it // //========================================================================== -unsigned char *FGLTexture::LoadHiresTexture(FTexture *tex, int *width, int *height, bool alphatexture) +unsigned char *FGLTexture::LoadHiresTexture(FTexture *tex, int *width, int *height) { if (HiresLump==-1) { @@ -131,8 +131,6 @@ unsigned char *FGLTexture::LoadHiresTexture(FTexture *tex, int *width, int *heig memset(buffer, 0, w * (h+1) * 4); FGLBitmap bmp(buffer, w*4, w, h); - if (alphatexture) bmp.SetAlphaTex(); - int trans = hirestexture->CopyTrueColorPixels(&bmp, 0, 0); hirestexture->CheckTrans(buffer, w*h, trans); @@ -181,7 +179,7 @@ void FGLTexture::Clean(bool all) // //=========================================================================== -unsigned char * FGLTexture::CreateTexBuffer(int translation, int & w, int & h, FTexture *hirescheck, bool alphatexture) +unsigned char * FGLTexture::CreateTexBuffer(int translation, int & w, int & h, FTexture *hirescheck) { unsigned char * buffer; int W, H; @@ -191,7 +189,7 @@ unsigned char * FGLTexture::CreateTexBuffer(int translation, int & w, int & h, F // by hires textures if (gl_texture_usehires && hirescheck != NULL) { - buffer = LoadHiresTexture (hirescheck, &w, &h, alphatexture); + buffer = LoadHiresTexture (hirescheck, &w, &h); if (buffer) { return buffer; @@ -207,7 +205,6 @@ unsigned char * FGLTexture::CreateTexBuffer(int translation, int & w, int & h, F FGLBitmap bmp(buffer, W*4, W, H); bmp.SetTranslationInfo(translation); - if (alphatexture) bmp.SetAlphaTex(); if (tex->bComplex) { @@ -241,7 +238,7 @@ unsigned char * FGLTexture::CreateTexBuffer(int translation, int & w, int & h, F // [BB] The hqnx upsampling (not the scaleN one) destroys partial transparency, don't upsamle textures using it. // [BB] Potentially upsample the buffer. - return gl_CreateUpsampledTextureBuffer ( tex, buffer, W, H, w, h, bIsTransparent || alphatexture); + return gl_CreateUpsampledTextureBuffer ( tex, buffer, W, H, w, h, !!bIsTransparent); } @@ -267,7 +264,7 @@ FHardwareTexture *FGLTexture::CreateHwTexture() // //=========================================================================== -const FHardwareTexture *FGLTexture::Bind(int texunit, int clampmode, int translation, bool alphatexture, FTexture *hirescheck) +const FHardwareTexture *FGLTexture::Bind(int texunit, int clampmode, int translation, FTexture *hirescheck) { int usebright = false; @@ -288,7 +285,7 @@ const FHardwareTexture *FGLTexture::Bind(int texunit, int clampmode, int transla } // Bind it to the system. - if (!hwtex->Bind(texunit, translation, alphatexture, needmipmap)) + if (!hwtex->Bind(texunit, translation, needmipmap)) { int w=0, h=0; @@ -298,10 +295,10 @@ const FHardwareTexture *FGLTexture::Bind(int texunit, int clampmode, int transla if (!tex->bHasCanvas) { - buffer = CreateTexBuffer(translation, w, h, hirescheck, alphatexture); + buffer = CreateTexBuffer(translation, w, h, hirescheck); tex->ProcessData(buffer, w, h, false); } - if (!hwtex->CreateTexture(buffer, w, h, texunit, needmipmap, translation, alphatexture)) + if (!hwtex->CreateTexture(buffer, w, h, texunit, needmipmap, translation)) { // could not create texture delete[] buffer; @@ -614,16 +611,14 @@ outl: static FMaterial *last; static int lastclamp; static int lasttrans; -static bool lastalpha; -void FMaterial::Bind(int clampmode, int translation, bool alphatexture) +void FMaterial::Bind(int clampmode, int translation) { // avoid rebinding the same texture multiple times. - if (this == last && lastclamp == clampmode && translation == lasttrans && lastalpha == alphatexture) return; + if (this == last && lastclamp == clampmode && translation == lasttrans) return; last = this; lastclamp = clampmode; - lastalpha = alphatexture; lasttrans = translation; int usebright = false; @@ -633,7 +628,7 @@ void FMaterial::Bind(int clampmode, int translation, bool alphatexture) if (tex->bHasCanvas) clampmode = CLAMP_CAMTEX; else if (tex->bWarped && clampmode <= CLAMP_XY) clampmode = CLAMP_NONE; - const FHardwareTexture *gltexture = mBaseLayer->Bind(0, clampmode, translation, alphatexture, allowhires? tex:NULL); + const FHardwareTexture *gltexture = mBaseLayer->Bind(0, clampmode, translation, allowhires? tex:NULL); if (gltexture != NULL) { for(unsigned i=0;igl_info.SystemTexture[mExpanded]->Bind(i+1, clampmode, 0, false, NULL); + layer->gl_info.SystemTexture[mExpanded]->Bind(i+1, clampmode, 0, NULL); maxbound = i+1; } } @@ -669,7 +664,7 @@ void FMaterial::Bind(int clampmode, int translation, bool alphatexture) //=========================================================================== void FMaterial::Precache() { - Bind(0, 0, false); + Bind(0, 0); } //=========================================================================== @@ -749,7 +744,7 @@ void FMaterial::BindToFrameBuffer() if (mBaseLayer->mHwTexture == NULL) { // must create the hardware texture first - mBaseLayer->Bind(0, 0, 0, false, NULL); + mBaseLayer->Bind(0, 0, 0, NULL); FHardwareTexture::Unbind(0); ClearLastTexture(); } diff --git a/src/gl/textures/gl_material.h b/src/gl/textures/gl_material.h index 6d3015a52e..b5f055d24a 100644 --- a/src/gl/textures/gl_material.h +++ b/src/gl/textures/gl_material.h @@ -67,18 +67,17 @@ private: bool bHasColorkey; // only for hires bool bExpand; - unsigned char * LoadHiresTexture(FTexture *hirescheck, int *width, int *height, bool alphatexture); + unsigned char * LoadHiresTexture(FTexture *hirescheck, int *width, int *height); FHardwareTexture *CreateHwTexture(); - const FHardwareTexture *Bind(int texunit, int clamp, int translation, bool alphatexture, FTexture *hirescheck); - const FHardwareTexture *BindPatch(int texunit, int translation, bool alphatexture); - + const FHardwareTexture *Bind(int texunit, int clamp, int translation, FTexture *hirescheck); + public: FGLTexture(FTexture * tx, bool expandpatches); ~FGLTexture(); - unsigned char * CreateTexBuffer(int translation, int & w, int & h, FTexture *hirescheck, bool alphatexture); + unsigned char * CreateTexBuffer(int translation, int & w, int & h, FTexture *hirescheck); void Clean(bool all); int Dump(int i); @@ -138,12 +137,11 @@ public: return mTextureLayers.Size() + 1; } - //void Bind(int clamp = 0, int translation = 0, int overrideshader = 0, bool alphatexture = false); - void Bind(int clamp, int translation, bool alphatexture); + void Bind(int clamp, int translation); unsigned char * CreateTexBuffer(int translation, int & w, int & h, bool allowhires=true) const { - return mBaseLayer->CreateTexBuffer(translation, w, h, allowhires? tex:NULL, 0); + return mBaseLayer->CreateTexBuffer(translation, w, h, allowhires? tex : NULL); } void Clean(bool f) diff --git a/src/r_data/r_translate.cpp b/src/r_data/r_translate.cpp index d11388e6e3..8d867f25f7 100644 --- a/src/r_data/r_translate.cpp +++ b/src/r_data/r_translate.cpp @@ -824,6 +824,15 @@ void R_InitTranslationTables () remap->Remap[i] = IcePaletteRemap[v]; remap->Palette[i] = PalEntry(255, IcePalette[v][0], IcePalette[v][1], IcePalette[v][2]); } + + // The alphatexture translation. Since alphatextures use the red channel this is just a standard grayscale mapping. + PushIdentityTable(TRANSLATION_Standard); + remap = translationtables[TRANSLATION_Standard][8]; + for (i = 0; i < 256; i++) + { + remap->Remap[i] = i; + remap->Palette[i] = PalEntry(255, i, i, i); + } } //---------------------------------------------------------------------------- diff --git a/wadsrc/static/shaders/glsl/main.fp b/wadsrc/static/shaders/glsl/main.fp index 532529f0bc..c77a058c20 100644 --- a/wadsrc/static/shaders/glsl/main.fp +++ b/wadsrc/static/shaders/glsl/main.fp @@ -60,17 +60,21 @@ vec4 getTexel(vec2 st) // switch (uTextureMode) { - case 1: + case 1: // TM_MASK texel.rgb = vec3(1.0,1.0,1.0); break; - case 2: + case 2: // TM_OPAQUE texel.a = 1.0; break; - case 3: + case 3: // TM_INVERSE texel = vec4(1.0-texel.r, 1.0-texel.b, 1.0-texel.g, texel.a); break; + + case 4: // TM_REDTOALPHA + texel = vec4(1.0, 1.0, 1.0, texel.r); + break; } texel *= uObjectColor;