diff --git a/source/common/textures/gametexture.h b/source/common/textures/gametexture.h index 5f32e1fdb..e1283e6de 100644 --- a/source/common/textures/gametexture.h +++ b/source/common/textures/gametexture.h @@ -91,7 +91,7 @@ class FGameTexture SpritePositioningInfo* spi = nullptr; ISoftwareTexture* SoftwareTexture = nullptr; - FMaterial* Material[4] = { }; + FMaterial* Material[5] = { }; // Material properties FVector2 detailScale = { 1.f, 1.f }; diff --git a/source/common/textures/hw_material.cpp b/source/common/textures/hw_material.cpp index c4a1ba9d3..a74514b87 100644 --- a/source/common/textures/hw_material.cpp +++ b/source/common/textures/hw_material.cpp @@ -29,6 +29,13 @@ #include "c_cvars.h" #include "v_video.h" +static IHardwareTexture* (*layercallback)(int layer, int translation); + +void FMaterial::SetLayerCallback(IHardwareTexture* (*cb)(int layer, int translation)) +{ + layercallback = cb; +} + //=========================================================================== // // Constructor @@ -42,8 +49,9 @@ FMaterial::FMaterial(FGameTexture * tx, int scaleflags) auto imgtex = tx->GetTexture(); mTextureLayers.Push({ imgtex, scaleflags, -1 }); - if (tx->GetUseType() == ETextureType::SWCanvas && static_cast(imgtex)->GetColorFormat() == 0) + if ((tx->GetUseType() == ETextureType::SWCanvas && static_cast(imgtex)->GetColorFormat() == 0) || (scaleflags & CTF_Indexed)) { + mTextureLayers[0].scaleFlags |= CTF_Indexed; mShaderIndex = SHADER_Paletted; } else if (tx->isHardwareCanvas()) @@ -57,74 +65,74 @@ FMaterial::FMaterial(FGameTexture * tx, int scaleflags) } else { - if (tx->isWarped()) + if (tx->isWarped()) + { + mShaderIndex = tx->isWarped(); // This picks SHADER_Warp1 or SHADER_Warp2 + } + // Note that the material takes no ownership of the texture! + else if (tx->Normal.get() && tx->Specular.get()) + { + for (auto& texture : { tx->Normal.get(), tx->Specular.get() }) { - mShaderIndex = tx->isWarped(); // This picks SHADER_Warp1 or SHADER_Warp2 + mTextureLayers.Push({ texture, 0, -1 }); } - // Note that the material takes no ownership of the texture! - else if (tx->Normal.get() && tx->Specular.get()) + mShaderIndex = SHADER_Specular; + } + else if (tx->Normal.get() && tx->Metallic.get() && tx->Roughness.get() && tx->AmbientOcclusion.get()) + { + for (auto& texture : { tx->Normal.get(), tx->Metallic.get(), tx->Roughness.get(), tx->AmbientOcclusion.get() }) { - for (auto &texture : { tx->Normal.get(), tx->Specular.get() }) - { - mTextureLayers.Push({ texture, 0, -1 }); - } - mShaderIndex = SHADER_Specular; - } - else if (tx->Normal.get() && tx->Metallic.get() && tx->Roughness.get() && tx->AmbientOcclusion.get()) - { - for (auto &texture : { tx->Normal.get(), tx->Metallic.get(), tx->Roughness.get(), tx->AmbientOcclusion.get() }) - { - mTextureLayers.Push({ texture, 0, -1 }); - } - mShaderIndex = SHADER_PBR; + mTextureLayers.Push({ texture, 0, -1 }); } + mShaderIndex = SHADER_PBR; + } - // Note that these layers must present a valid texture even if not used, because empty TMUs in the shader are an undefined condition. - tx->CreateDefaultBrightmap(); - auto placeholder = TexMan.GameByIndex(1); - if (tx->Brightmap.get()) - { - mTextureLayers.Push({ tx->Brightmap.get(), scaleflags, -1 }); - mLayerFlags |= TEXF_Brightmap; - } - else - { - mTextureLayers.Push({ placeholder->GetTexture(), 0, -1 }); - } - if (tx->Detailmap.get()) - { - mTextureLayers.Push({ tx->Detailmap.get(), 0, CLAMP_NONE }); - mLayerFlags |= TEXF_Detailmap; - } - else - { - mTextureLayers.Push({ placeholder->GetTexture(), 0, -1 }); - } - if (tx->Glowmap.get()) - { - mTextureLayers.Push({ tx->Glowmap.get(), scaleflags, -1 }); - mLayerFlags |= TEXF_Glowmap; - } - else - { - mTextureLayers.Push({ placeholder->GetTexture(), 0, -1 }); - } + // Note that these layers must present a valid texture even if not used, because empty TMUs in the shader are an undefined condition. + tx->CreateDefaultBrightmap(); + auto placeholder = TexMan.GameByIndex(1); + if (tx->Brightmap.get()) + { + mTextureLayers.Push({ tx->Brightmap.get(), scaleflags, -1 }); + mLayerFlags |= TEXF_Brightmap; + } + else + { + mTextureLayers.Push({ placeholder->GetTexture(), 0, -1 }); + } + if (tx->Detailmap.get()) + { + mTextureLayers.Push({ tx->Detailmap.get(), 0, CLAMP_NONE }); + mLayerFlags |= TEXF_Detailmap; + } + else + { + mTextureLayers.Push({ placeholder->GetTexture(), 0, -1 }); + } + if (tx->Glowmap.get()) + { + mTextureLayers.Push({ tx->Glowmap.get(), scaleflags, -1 }); + mLayerFlags |= TEXF_Glowmap; + } + else + { + mTextureLayers.Push({ placeholder->GetTexture(), 0, -1 }); + } - auto index = tx->GetShaderIndex(); - if (index >= FIRST_USER_SHADER) + auto index = tx->GetShaderIndex(); + if (index >= FIRST_USER_SHADER) + { + const UserShaderDesc& usershader = usershaders[index - FIRST_USER_SHADER]; + if (usershader.shaderType == mShaderIndex) // Only apply user shader if it matches the expected material { - const UserShaderDesc &usershader = usershaders[index - FIRST_USER_SHADER]; - if (usershader.shaderType == mShaderIndex) // Only apply user shader if it matches the expected material + for (auto& texture : tx->CustomShaderTextures) { - for (auto &texture : tx->CustomShaderTextures) - { - if (texture == nullptr) continue; - mTextureLayers.Push({ texture.get(), 0 }); // scalability should be user-definable. - } - mShaderIndex = index; + if (texture == nullptr) continue; + mTextureLayers.Push({ texture.get(), 0 }); // scalability should be user-definable. } + mShaderIndex = index; } } + } mScaleFlags = scaleflags; mTextureLayers.ShrinkToFit(); @@ -149,12 +157,25 @@ FMaterial::~FMaterial() // //=========================================================================== -IHardwareTexture *FMaterial::GetLayer(int i, int translation, MaterialLayerInfo **pLayer) const +IHardwareTexture* FMaterial::GetLayer(int i, int translation, MaterialLayerInfo** pLayer) const { - auto &layer = mTextureLayers[i]; - if (pLayer) *pLayer = &layer; - - if (layer.layerTexture) return layer.layerTexture->GetHardwareTexture(translation, layer.scaleFlags); + if (mShaderIndex == SHADER_Paletted && i > 0 && layercallback) + { + static MaterialLayerInfo deflayer = { nullptr, 0, CLAMP_XY }; + if (i == 1 || i == 2) + { + if (pLayer) *pLayer = &deflayer; + //This must be done with a user supplied callback because we cannot set up the rules for palette data selection here + return layercallback(i, translation); + } + } + else + { + auto& layer = mTextureLayers[i]; + if (pLayer) *pLayer = &layer; + if (mShaderIndex == SHADER_Paletted) translation = -1; + if (layer.layerTexture) return layer.layerTexture->GetHardwareTexture(translation, layer.scaleFlags); + } return nullptr; } @@ -169,6 +190,7 @@ FMaterial * FMaterial::ValidateTexture(FGameTexture * gtex, int scaleflags, bool { if (gtex && gtex->isValid()) { + if (scaleflags & CTF_Indexed) scaleflags = CTF_Indexed; if (!gtex->expandSprites()) scaleflags &= ~CTF_Expand; FMaterial *hwtex = gtex->Material[scaleflags]; diff --git a/source/common/textures/hw_material.h b/source/common/textures/hw_material.h index 75a77e35a..20c38b332 100644 --- a/source/common/textures/hw_material.h +++ b/source/common/textures/hw_material.h @@ -30,6 +30,8 @@ class FMaterial int mScaleFlags; public: + static void SetLayerCallback(IHardwareTexture* (*layercallback)(int layer, int translation)); + FGameTexture *sourcetex; // the owning texture. FMaterial(FGameTexture *tex, int scaleflags); diff --git a/source/common/textures/hw_texcontainer.h b/source/common/textures/hw_texcontainer.h index a29fc6396..9a00e848a 100644 --- a/source/common/textures/hw_texcontainer.h +++ b/source/common/textures/hw_texcontainer.h @@ -12,9 +12,9 @@ enum ECreateTexBufferFlags CTF_Expand = 1, // create buffer with a one-pixel wide border CTF_Upscale = 2, // Upscale the texture CTF_CreateMask = 3, // Flags that are relevant for hardware texture creation. - CTF_ProcessData = 4, // run postprocessing on the generated buffer. This is only needed when using the data for a hardware texture. - CTF_CheckOnly = 8, // Only runs the code to get a content ID but does not create a texture. Can be used to access a caching system for the hardware textures. - CTF_Indexed = 16 // Tell the backend to create an indexed texture. + CTF_Indexed = 4, // Tell the backend to create an indexed texture. + CTF_ProcessData = 8, // run postprocessing on the generated buffer. This is only needed when using the data for a hardware texture. + CTF_CheckOnly = 16, // Only runs the code to get a content ID but does not create a texture. Can be used to access a caching system for the hardware textures. }; class FHardwareTextureContainer diff --git a/source/common/textures/texture.cpp b/source/common/textures/texture.cpp index 20a8d9776..97ac7b20a 100644 --- a/source/common/textures/texture.cpp +++ b/source/common/textures/texture.cpp @@ -527,17 +527,15 @@ outl: IHardwareTexture* FTexture::GetHardwareTexture(int translation, int scaleflags) { - //if (UseType != ETextureType::Null) + int indexed = scaleflags & CTF_Indexed; + if (indexed) translation = -1; + IHardwareTexture* hwtex = SystemTextures.GetHardwareTexture(translation, scaleflags); + if (hwtex == nullptr) { - IHardwareTexture* hwtex = SystemTextures.GetHardwareTexture(translation, scaleflags); - if (hwtex == nullptr) - { - hwtex = screen->CreateHardwareTexture(4); - SystemTextures.AddHardwareTexture(translation, scaleflags, hwtex); + hwtex = screen->CreateHardwareTexture(indexed? 1 : 4); + SystemTextures.AddHardwareTexture(translation, scaleflags, hwtex); } - return hwtex; - } - return nullptr; + return hwtex; } diff --git a/source/duke3d/src/sector.cpp b/source/duke3d/src/sector.cpp index e5e11b4d7..c90a40bd6 100644 --- a/source/duke3d/src/sector.cpp +++ b/source/duke3d/src/sector.cpp @@ -393,7 +393,6 @@ static void G_SetupCamTile(int spriteNum, int tileNum, int smoothRatio) screen->RenderTextureView(canvas, [=](IntRect& rect) { - // Beware! Apparently this is allowed to render to the camera itself. Breakage is basically guarenteed... if (VM_OnEventWithReturn(EVENT_DISPLAYROOMSCAMERATILE, spriteNum, screenpeek, 0) != 1) { yax_preparedrawrooms(); diff --git a/source/glbackend/gl_texture.cpp b/source/glbackend/gl_texture.cpp index fbe3f95ad..86176ab0a 100644 --- a/source/glbackend/gl_texture.cpp +++ b/source/glbackend/gl_texture.cpp @@ -78,7 +78,8 @@ bool GLInstance::SetTexture(int picnum, FGameTexture* tex, int paletteid, int sa SetBasepalTint(texpick.basepalTint); auto &mat = renderState.mMaterial; - mat.mMaterial = FMaterial::ValidateTexture(tex, 0); // todo allow scaling + int flags = hw_useindexedcolortextures ? CTF_Indexed : 0; + mat.mMaterial = FMaterial::ValidateTexture(tex, flags); // todo allow scaling mat.mClampMode = sampler; mat.mTranslation = texpick.translation; mat.mOverrideShader = 0; diff --git a/wadsrc/static/engine/menudef.txt b/wadsrc/static/engine/menudef.txt index e817797b1..9a59b960a 100644 --- a/wadsrc/static/engine/menudef.txt +++ b/wadsrc/static/engine/menudef.txt @@ -1577,7 +1577,10 @@ OptionValue GPUSwitch OptionMenu VideoModeMenu //protected { Title "$VIDMNU_TITLE" - + + // does not work yet. + //Option "$VIDMNU_PREFERBACKEND", "vid_preferbackend", "PreferBackend" + //StaticText " " Option "$VIDMNU_FULLSCREEN", "vid_fullscreen", "YesNo" IfOption(Mac)