mirror of
https://github.com/ZDoom/gzdoom.git
synced 2025-02-17 01:31:25 +00:00
Configurable sampling per custom texture in material shaders
This commit is contained in:
parent
494ec1b3f9
commit
5e24582c3c
9 changed files with 117 additions and 27 deletions
|
@ -361,7 +361,7 @@ void Wiper_Burn::SetTextures(FGameTexture *startscreen, FGameTexture *endscreen)
|
|||
BurnTexture = new FBurnTexture(WIDTH, HEIGHT);
|
||||
auto mat = FMaterial::ValidateTexture(endScreen, false);
|
||||
mat->ClearLayers();
|
||||
mat->AddTextureLayer(BurnTexture, false);
|
||||
mat->AddTextureLayer(BurnTexture, false, MaterialLayerSampling::Default);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
|
|
@ -85,7 +85,7 @@ void VkSamplerManager::ResetHWSamplers()
|
|||
|
||||
void VkSamplerManager::CreateHWSamplers()
|
||||
{
|
||||
int filter = sysCallbacks.DisableTextureFilter && sysCallbacks.DisableTextureFilter()? 0 : gl_texture_filter;
|
||||
int filter = sysCallbacks.DisableTextureFilter && sysCallbacks.DisableTextureFilter() ? 0 : gl_texture_filter;
|
||||
|
||||
for (int i = CLAMP_NONE; i <= CLAMP_XY; i++)
|
||||
{
|
||||
|
@ -137,15 +137,40 @@ void VkSamplerManager::CreateHWSamplers()
|
|||
.MaxLod(0.25f)
|
||||
.DebugName("VkSamplerManager.mSamplers")
|
||||
.Create(fb->GetDevice());
|
||||
|
||||
|
||||
mOverrideSamplers[int(MaterialLayerSampling::NearestMipLinear)] = SamplerBuilder()
|
||||
.MagFilter(VK_FILTER_NEAREST)
|
||||
.MinFilter(VK_FILTER_LINEAR)
|
||||
.AddressMode(VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_REPEAT)
|
||||
.MipmapMode(VK_SAMPLER_MIPMAP_MODE_LINEAR)
|
||||
.MaxLod(100.0f)
|
||||
.Anisotropy(gl_texture_filter_anisotropic)
|
||||
.Create(fb->GetDevice());
|
||||
|
||||
mOverrideSamplers[int(MaterialLayerSampling::LinearMipLinear)] = SamplerBuilder()
|
||||
.MagFilter(VK_FILTER_LINEAR)
|
||||
.MinFilter(VK_FILTER_LINEAR)
|
||||
.AddressMode(VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_REPEAT)
|
||||
.MipmapMode(VK_SAMPLER_MIPMAP_MODE_LINEAR)
|
||||
.MaxLod(100.0f)
|
||||
.Anisotropy(gl_texture_filter_anisotropic)
|
||||
.Create(fb->GetDevice());
|
||||
}
|
||||
|
||||
void VkSamplerManager::DeleteHWSamplers()
|
||||
{
|
||||
for (auto& sampler : mSamplers)
|
||||
auto deleteSamplers = [&](auto& samplers)
|
||||
{
|
||||
if (sampler)
|
||||
fb->GetCommands()->DrawDeleteList->Add(std::move(sampler));
|
||||
}
|
||||
for (auto& sampler : samplers)
|
||||
{
|
||||
if (sampler)
|
||||
fb->GetCommands()->DrawDeleteList->Add(std::move(sampler));
|
||||
}
|
||||
};
|
||||
|
||||
deleteSamplers(mSamplers);
|
||||
deleteSamplers(mOverrideSamplers);
|
||||
}
|
||||
|
||||
VulkanSampler* VkSamplerManager::Get(PPFilterMode filter, PPWrapMode wrap)
|
||||
|
|
|
@ -16,9 +16,16 @@ public:
|
|||
|
||||
void ResetHWSamplers();
|
||||
|
||||
VulkanSampler *Get(int no) const { return mSamplers[no].get(); }
|
||||
VulkanSampler* Get(PPFilterMode filter, PPWrapMode wrap);
|
||||
|
||||
inline VulkanSampler* Get(int no) const { return mSamplers[no].get(); }
|
||||
inline VulkanSampler* Get(MaterialLayerSampling filterOverride, int no) const
|
||||
{
|
||||
if (filterOverride == MaterialLayerSampling::Default)
|
||||
return Get(no);
|
||||
return mOverrideSamplers[int(filterOverride)].get();
|
||||
}
|
||||
|
||||
std::unique_ptr<VulkanSampler> ShadowmapSampler;
|
||||
std::unique_ptr<VulkanSampler> LightmapSampler;
|
||||
|
||||
|
@ -30,5 +37,6 @@ private:
|
|||
|
||||
VulkanRenderDevice* fb = nullptr;
|
||||
std::array<std::unique_ptr<VulkanSampler>, NUMSAMPLERS> mSamplers;
|
||||
std::array<std::unique_ptr<VulkanSampler>, 2> mOverrideSamplers;
|
||||
std::array<std::unique_ptr<VulkanSampler>, 4> mPPSamplers;
|
||||
};
|
||||
|
|
|
@ -350,13 +350,13 @@ VulkanDescriptorSet* VkMaterial::GetDescriptorSet(const FMaterialState& state)
|
|||
|
||||
descriptor->SetDebugName("VkHardwareTexture.mDescriptorSets");
|
||||
|
||||
VulkanSampler* sampler = fb->GetSamplerManager()->Get(clampmode);
|
||||
auto* sampler = fb->GetSamplerManager()->Get(clampmode);
|
||||
|
||||
WriteDescriptors update;
|
||||
MaterialLayerInfo *layer;
|
||||
auto systex = static_cast<VkHardwareTexture*>(GetLayer(0, state.mTranslation, &layer));
|
||||
auto systeximage = systex->GetImage(layer->layerTexture, state.mTranslation, layer->scaleFlags);
|
||||
update.AddCombinedImageSampler(descriptor.get(), 0, systeximage->View.get(), sampler, systeximage->Layout);
|
||||
update.AddCombinedImageSampler(descriptor.get(), 0, systeximage->View.get(), fb->GetSamplerManager()->Get(GetLayerFilter(0), clampmode), systeximage->Layout);
|
||||
|
||||
if (!(layer->scaleFlags & CTF_Indexed))
|
||||
{
|
||||
|
@ -364,7 +364,7 @@ VulkanDescriptorSet* VkMaterial::GetDescriptorSet(const FMaterialState& state)
|
|||
{
|
||||
auto syslayer = static_cast<VkHardwareTexture*>(GetLayer(i, 0, &layer));
|
||||
auto syslayerimage = syslayer->GetImage(layer->layerTexture, 0, layer->scaleFlags);
|
||||
update.AddCombinedImageSampler(descriptor.get(), i, syslayerimage->View.get(), sampler, syslayerimage->Layout);
|
||||
update.AddCombinedImageSampler(descriptor.get(), i, syslayerimage->View.get(), fb->GetSamplerManager()->Get(GetLayerFilter(i), clampmode), syslayerimage->Layout);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -373,7 +373,7 @@ VulkanDescriptorSet* VkMaterial::GetDescriptorSet(const FMaterialState& state)
|
|||
{
|
||||
auto syslayer = static_cast<VkHardwareTexture*>(GetLayer(i, translation, &layer));
|
||||
auto syslayerimage = syslayer->GetImage(layer->layerTexture, 0, layer->scaleFlags);
|
||||
update.AddCombinedImageSampler(descriptor.get(), i, syslayerimage->View.get(), sampler, syslayerimage->Layout);
|
||||
update.AddCombinedImageSampler(descriptor.get(), i, syslayerimage->View.get(), fb->GetSamplerManager()->Get(GetLayerFilter(i), clampmode), syslayerimage->Layout);
|
||||
}
|
||||
numLayers = 3;
|
||||
}
|
||||
|
|
|
@ -35,6 +35,14 @@ struct SpritePositioningInfo
|
|||
|
||||
};
|
||||
|
||||
enum class MaterialLayerSampling
|
||||
{
|
||||
Default = -1,
|
||||
|
||||
NearestMipLinear,
|
||||
LinearMipLinear,
|
||||
};
|
||||
|
||||
struct MaterialLayers
|
||||
{
|
||||
float Glossiness;
|
||||
|
@ -46,6 +54,8 @@ struct MaterialLayers
|
|||
FGameTexture* Roughness;
|
||||
FGameTexture* AmbientOcclusion;
|
||||
FGameTexture* CustomShaderTextures[MAX_CUSTOM_HW_SHADER_TEXTURES];
|
||||
|
||||
MaterialLayerSampling CustomShaderTextureSampling[MAX_CUSTOM_HW_SHADER_TEXTURES];
|
||||
};
|
||||
|
||||
enum EGameTexFlags
|
||||
|
@ -74,6 +84,8 @@ struct FMaterialLayers
|
|||
RefCountedPtr<FTexture> Roughness; // Roughness texture for PBR
|
||||
RefCountedPtr<FTexture> AmbientOcclusion; // Ambient occlusion texture for PBR
|
||||
RefCountedPtr<FTexture> CustomShaderTextures[MAX_CUSTOM_HW_SHADER_TEXTURES]; // Custom texture maps for custom hardware shaders
|
||||
|
||||
MaterialLayerSampling CustomShaderTextureSampling[MAX_CUSTOM_HW_SHADER_TEXTURES];
|
||||
};
|
||||
|
||||
// Refactoring helper to allow piece by piece adjustment of the API
|
||||
|
@ -235,7 +247,11 @@ public:
|
|||
if (lay.AmbientOcclusion) Layers->AmbientOcclusion = lay.AmbientOcclusion->GetTexture();
|
||||
for (int i = 0; i < MAX_CUSTOM_HW_SHADER_TEXTURES; i++)
|
||||
{
|
||||
if (lay.CustomShaderTextures[i]) Layers->CustomShaderTextures[i] = lay.CustomShaderTextures[i]->GetTexture();
|
||||
if (lay.CustomShaderTextures[i])
|
||||
{
|
||||
Layers->CustomShaderTextureSampling[i] = lay.CustomShaderTextureSampling[i];
|
||||
Layers->CustomShaderTextures[i] = lay.CustomShaderTextures[i]->GetTexture();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,7 +52,7 @@ FMaterial::FMaterial(FGameTexture * tx, int scaleflags)
|
|||
mShaderIndex = SHADER_Default;
|
||||
sourcetex = tx;
|
||||
auto imgtex = tx->GetTexture();
|
||||
mTextureLayers.Push({ imgtex, scaleflags, -1 });
|
||||
mTextureLayers.Push({ imgtex, scaleflags, -1, MaterialLayerSampling::Default });
|
||||
|
||||
if (tx->GetUseType() == ETextureType::SWCanvas && static_cast<FWrapperTexture*>(imgtex)->GetColorFormat() == 0)
|
||||
{
|
||||
|
@ -83,7 +83,7 @@ FMaterial::FMaterial(FGameTexture * tx, int scaleflags)
|
|||
{
|
||||
for (auto &texture : { tx->Layers->Normal.get(), tx->Layers->Specular.get() })
|
||||
{
|
||||
mTextureLayers.Push({ texture, 0, -1 });
|
||||
mTextureLayers.Push({ texture, 0, -1, MaterialLayerSampling::Default });
|
||||
}
|
||||
mShaderIndex = SHADER_Specular;
|
||||
}
|
||||
|
@ -91,7 +91,7 @@ FMaterial::FMaterial(FGameTexture * tx, int scaleflags)
|
|||
{
|
||||
for (auto &texture : { tx->Layers->Normal.get(), tx->Layers->Metallic.get(), tx->Layers->Roughness.get(), tx->Layers->AmbientOcclusion.get() })
|
||||
{
|
||||
mTextureLayers.Push({ texture, 0, -1 });
|
||||
mTextureLayers.Push({ texture, 0, -1, MaterialLayerSampling::Default });
|
||||
}
|
||||
mShaderIndex = SHADER_PBR;
|
||||
}
|
||||
|
@ -101,30 +101,30 @@ FMaterial::FMaterial(FGameTexture * tx, int scaleflags)
|
|||
auto placeholder = TexMan.GameByIndex(1);
|
||||
if (tx->Brightmap.get())
|
||||
{
|
||||
mTextureLayers.Push({ tx->Brightmap.get(), scaleflags, -1 });
|
||||
mTextureLayers.Push({ tx->Brightmap.get(), scaleflags, -1, MaterialLayerSampling::Default });
|
||||
mLayerFlags |= TEXF_Brightmap;
|
||||
}
|
||||
else
|
||||
{
|
||||
mTextureLayers.Push({ placeholder->GetTexture(), 0, -1 });
|
||||
mTextureLayers.Push({ placeholder->GetTexture(), 0, -1, MaterialLayerSampling::Default });
|
||||
}
|
||||
if (tx->Layers && tx->Layers->Detailmap.get())
|
||||
{
|
||||
mTextureLayers.Push({ tx->Layers->Detailmap.get(), 0, CLAMP_NONE });
|
||||
mTextureLayers.Push({ tx->Layers->Detailmap.get(), 0, CLAMP_NONE, MaterialLayerSampling::Default });
|
||||
mLayerFlags |= TEXF_Detailmap;
|
||||
}
|
||||
else
|
||||
{
|
||||
mTextureLayers.Push({ placeholder->GetTexture(), 0, -1 });
|
||||
mTextureLayers.Push({ placeholder->GetTexture(), 0, -1, MaterialLayerSampling::Default });
|
||||
}
|
||||
if (tx->Layers && tx->Layers->Glowmap.get())
|
||||
{
|
||||
mTextureLayers.Push({ tx->Layers->Glowmap.get(), scaleflags, -1 });
|
||||
mTextureLayers.Push({ tx->Layers->Glowmap.get(), scaleflags, -1, MaterialLayerSampling::Default});
|
||||
mLayerFlags |= TEXF_Glowmap;
|
||||
}
|
||||
else
|
||||
{
|
||||
mTextureLayers.Push({ placeholder->GetTexture(), 0, -1 });
|
||||
mTextureLayers.Push({ placeholder->GetTexture(), 0, -1, MaterialLayerSampling::Default });
|
||||
}
|
||||
|
||||
auto index = tx->GetShaderIndex();
|
||||
|
@ -137,10 +137,13 @@ FMaterial::FMaterial(FGameTexture * tx, int scaleflags)
|
|||
{
|
||||
if (tx->Layers)
|
||||
{
|
||||
size_t index = 0;
|
||||
for (auto& texture : tx->Layers->CustomShaderTextures)
|
||||
{
|
||||
if (texture == nullptr) continue;
|
||||
mTextureLayers.Push({ texture.get(), 0 }); // scalability should be user-definable.
|
||||
if (texture != nullptr)
|
||||
{
|
||||
mTextureLayers.Push({ texture.get(), 0, -1, tx->Layers->CustomShaderTextureSampling[index++]}); // scalability should be user-definable.
|
||||
}
|
||||
}
|
||||
}
|
||||
mShaderIndex = index;
|
||||
|
|
|
@ -13,6 +13,7 @@ struct MaterialLayerInfo
|
|||
FTexture* layerTexture;
|
||||
int scaleFlags;
|
||||
int clampflags;
|
||||
MaterialLayerSampling layerFiltering;
|
||||
};
|
||||
|
||||
//===========================================================================
|
||||
|
@ -55,9 +56,9 @@ public:
|
|||
mTextureLayers.Resize(1);
|
||||
}
|
||||
|
||||
void AddTextureLayer(FTexture *tex, bool allowscale)
|
||||
void AddTextureLayer(FTexture *tex, bool allowscale, MaterialLayerSampling filter)
|
||||
{
|
||||
mTextureLayers.Push({ tex, allowscale });
|
||||
mTextureLayers.Push({ tex, allowscale, -1, filter });
|
||||
}
|
||||
|
||||
int NumLayers() const
|
||||
|
@ -66,7 +67,11 @@ public:
|
|||
}
|
||||
|
||||
IHardwareTexture *GetLayer(int i, int translation, MaterialLayerInfo **pLayer = nullptr) const;
|
||||
|
||||
|
||||
MaterialLayerSampling GetLayerFilter(int index) const
|
||||
{
|
||||
return mTextureLayers[index].layerFiltering;
|
||||
}
|
||||
|
||||
static FMaterial *ValidateTexture(FGameTexture * tex, int scaleflags, bool create = true);
|
||||
const TArray<MaterialLayerInfo> &GetLayerArray() const
|
||||
|
|
|
@ -1371,6 +1371,7 @@ class GLDefsParser
|
|||
if (tex)
|
||||
{
|
||||
bool okay = false;
|
||||
size_t texIndex = 0;
|
||||
for (size_t i = 0; i < countof(mlay.CustomShaderTextures); i++)
|
||||
{
|
||||
if (!mlay.CustomShaderTextures[i])
|
||||
|
@ -1383,6 +1384,7 @@ class GLDefsParser
|
|||
|
||||
texNameList.Push(textureName);
|
||||
texNameIndex.Push((int)i);
|
||||
texIndex = i;
|
||||
okay = true;
|
||||
break;
|
||||
}
|
||||
|
@ -1391,6 +1393,34 @@ class GLDefsParser
|
|||
{
|
||||
sc.ScriptError("Error: out of texture units in texture '%s'", tex->GetName().GetChars());
|
||||
}
|
||||
|
||||
if (sc.CheckToken('{'))
|
||||
{
|
||||
while (!sc.CheckToken('}'))
|
||||
{
|
||||
sc.MustGetString();
|
||||
if (sc.Compare("filter"))
|
||||
{
|
||||
sc.MustGetString();
|
||||
if (sc.Compare("nearest"))
|
||||
{
|
||||
mlay.CustomShaderTextureSampling[texIndex] = MaterialLayerSampling::NearestMipLinear;
|
||||
}
|
||||
else if (sc.Compare("linear"))
|
||||
{
|
||||
mlay.CustomShaderTextureSampling[texIndex] = MaterialLayerSampling::LinearMipLinear;
|
||||
}
|
||||
else if (sc.Compare("default"))
|
||||
{
|
||||
mlay.CustomShaderTextureSampling[texIndex] = MaterialLayerSampling::Default;
|
||||
}
|
||||
else
|
||||
{
|
||||
sc.ScriptError("Error: unexpected '%s' when reading filter property in texture '%s'\n", sc.String, tex ? tex->GetName().GetChars() : "(null)");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (sc.Compare("define"))
|
||||
|
@ -1758,10 +1788,12 @@ class GLDefsParser
|
|||
}
|
||||
sc.MustGetString();
|
||||
bool okay = false;
|
||||
size_t texIndex = 0;
|
||||
for (size_t i = 0; i < countof(mlay.CustomShaderTextures); i++)
|
||||
{
|
||||
if (!mlay.CustomShaderTextures[i])
|
||||
{
|
||||
mlay.CustomShaderTextureSampling[texIndex] = MaterialLayerSampling::Default;
|
||||
mlay.CustomShaderTextures[i] = TexMan.FindGameTexture(sc.String, ETextureType::Any, FTextureManager::TEXMAN_TryAny);
|
||||
if (!mlay.CustomShaderTextures[i])
|
||||
{
|
||||
|
@ -1770,6 +1802,7 @@ class GLDefsParser
|
|||
|
||||
texNameList.Push(textureName);
|
||||
texNameIndex.Push((int)i);
|
||||
texIndex = i;
|
||||
okay = true;
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -102,7 +102,7 @@ sector_t *SWSceneDrawer::RenderView(player_t *player)
|
|||
fbtex.reset(MakeGameTexture(new FWrapperTexture(screen->GetWidth(), screen->GetHeight(), V_IsTrueColor()), nullptr, ETextureType::SWCanvas));
|
||||
GetSystemTexture()->AllocateBuffer(screen->GetWidth(), screen->GetHeight(), V_IsTrueColor() ? 4 : 1);
|
||||
auto mat = FMaterial::ValidateTexture(fbtex.get(), false);
|
||||
mat->AddTextureLayer(PaletteTexture, false);
|
||||
mat->AddTextureLayer(PaletteTexture, false, MaterialLayerSampling::Default);
|
||||
|
||||
Canvas.reset();
|
||||
Canvas.reset(new DCanvas(screen->GetWidth(), screen->GetHeight(), V_IsTrueColor()));
|
||||
|
|
Loading…
Reference in a new issue