Render scene with indexed textures for vid_rendermode 2
This commit is contained in:
parent
783a3524ed
commit
990ce7c6c9
28 changed files with 380 additions and 127 deletions
|
|
@ -64,4 +64,17 @@ struct FColormap
|
|||
|
||||
};
|
||||
|
||||
struct FSWColormap
|
||||
{
|
||||
uint8_t* Maps = nullptr;
|
||||
PalEntry Color = 0xffffffff;
|
||||
PalEntry Fade = 0xff000000;
|
||||
int Desaturate = 0;
|
||||
|
||||
struct
|
||||
{
|
||||
int textureIndex = -1;
|
||||
int bindIndex = -1;
|
||||
} Renderdev;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ struct FMaterialState
|
|||
int mTranslation = CLAMP_NONE;
|
||||
int mOverrideShader = -1;
|
||||
bool mChanged = false;
|
||||
bool mPaletteMode = false;
|
||||
GlobalShaderAddr globalShaderAddr = {0, 3, 0}; // null global shader entry, TODO
|
||||
|
||||
void Reset()
|
||||
|
|
@ -21,6 +22,7 @@ struct FMaterialState
|
|||
mClampMode = CLAMP_NONE;
|
||||
mOverrideShader = -1;
|
||||
mChanged = false;
|
||||
mPaletteMode = false;
|
||||
globalShaderAddr = {0, 3, 0};
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ struct FColormap;
|
|||
class IBuffer;
|
||||
struct HWViewpointUniforms;
|
||||
struct FDynLightData;
|
||||
struct FSWColormap;
|
||||
enum class LevelMeshDrawType;
|
||||
|
||||
enum EClearTarget
|
||||
|
|
@ -159,6 +160,9 @@ protected:
|
|||
int mColorMapSpecial;
|
||||
float mColorMapFlash;
|
||||
|
||||
bool mPaletteMode = false;
|
||||
FSWColormap* mSWColormap = nullptr;
|
||||
|
||||
SurfaceUniforms mSurfaceUniforms = {};
|
||||
PalEntry mFogColor;
|
||||
|
||||
|
|
@ -223,6 +227,8 @@ public:
|
|||
mMaterial.Reset();
|
||||
mBias.Reset();
|
||||
mPassType = NORMAL_PASS;
|
||||
mPaletteMode = false;
|
||||
mSWColormap = nullptr;
|
||||
|
||||
mColorMapSpecial = 0;
|
||||
mColorMapFlash = 1;
|
||||
|
|
@ -621,6 +627,16 @@ public:
|
|||
SetMaterial(tex, upscalemask, scaleflags, clampmode, translation.index(), overrideshader, cls);
|
||||
}
|
||||
|
||||
void SetPaletteMode(bool palette)
|
||||
{
|
||||
mPaletteMode = palette;
|
||||
}
|
||||
|
||||
void SetSWColormap(FSWColormap* cm)
|
||||
{
|
||||
mSWColormap = cm;
|
||||
}
|
||||
|
||||
void SetClipSplit(float bottom, float top)
|
||||
{
|
||||
mSurfaceUniforms.uClipSplit.X = bottom;
|
||||
|
|
|
|||
|
|
@ -44,10 +44,10 @@ struct SurfaceUniforms
|
|||
|
||||
float uAlphaThreshold;
|
||||
int uTextureIndex;
|
||||
float uDepthFadeThreshold;
|
||||
int uColormapIndex;
|
||||
int uLightProbeIndex;
|
||||
FVector3 uActorCenter;
|
||||
float padding2;
|
||||
float uDepthFadeThreshold;
|
||||
};
|
||||
|
||||
struct SurfaceLightUniforms
|
||||
|
|
|
|||
|
|
@ -227,7 +227,7 @@ public:
|
|||
virtual void SetActiveRenderTarget() {}
|
||||
|
||||
// Get the array index for the material in the textures array accessible from shaders
|
||||
virtual int GetBindlessTextureIndex(FMaterial* material, int clampmode, int translation) { return -1; }
|
||||
virtual int GetBindlessTextureIndex(FMaterial* material, int clampmode, int translation, bool paletteMode) { return -1; }
|
||||
|
||||
virtual void RenderEnvironmentMap(std::function<void(IntRect& bounds, int side)> renderFunc, TArrayView<uint16_t>& irradianceMap, TArrayView<uint16_t>& prefilterMap) {}
|
||||
virtual void UploadEnvironmentMaps(int cubemapCount, const TArray<uint16_t>& irradianceMaps, const TArray<uint16_t>& prefilterMaps) {}
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@
|
|||
#include "flatvertices.h"
|
||||
#include "hw_viewpointuniforms.h"
|
||||
#include "v_2ddrawer.h"
|
||||
#include "fcolormap.h"
|
||||
|
||||
VkDescriptorSetManager::VkDescriptorSetManager(VulkanRenderDevice* fb) : fb(fb)
|
||||
{
|
||||
|
|
@ -170,6 +171,10 @@ void VkDescriptorSetManager::ResetHWTextureSets()
|
|||
for (auto mat : Materials)
|
||||
mat->DeleteDescriptors();
|
||||
|
||||
for (FSWColormap* colormap : Colormaps)
|
||||
colormap->Renderdev.bindIndex = -1;
|
||||
Colormaps.clear();
|
||||
|
||||
Bindless.Writer = WriteDescriptors();
|
||||
Bindless.NextIndex = 0;
|
||||
|
||||
|
|
@ -178,6 +183,9 @@ void VkDescriptorSetManager::ResetHWTextureSets()
|
|||
|
||||
// And slot 1 is always our BRDF LUT texture
|
||||
AddBindlessTextureIndex(fb->GetTextureManager()->GetBrdfLutTextureView(), fb->GetSamplerManager()->Get(CLAMP_XY_NOMIP));
|
||||
|
||||
// Slot 2 is always our game palette texture
|
||||
AddBindlessTextureIndex(fb->GetTextureManager()->GetGamePaletteView(), fb->GetSamplerManager()->Get(CLAMP_XY_NOMIP));
|
||||
}
|
||||
|
||||
void VkDescriptorSetManager::AddMaterial(VkMaterial* texture)
|
||||
|
|
@ -408,3 +416,13 @@ int VkDescriptorSetManager::AddBindlessTextureIndex(VulkanImageView* imageview,
|
|||
Bindless.Writer.AddCombinedImageSampler(Bindless.Set.get(), 0, index, imageview, sampler, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
||||
return index;
|
||||
}
|
||||
|
||||
int VkDescriptorSetManager::GetSWColormapTextureIndex(FSWColormap* colormap)
|
||||
{
|
||||
if (colormap->Renderdev.bindIndex != -1)
|
||||
return colormap->Renderdev.bindIndex;
|
||||
|
||||
colormap->Renderdev.bindIndex = AddBindlessTextureIndex(fb->GetTextureManager()->GetSWColormapView(colormap), fb->GetSamplerManager()->Get(CLAMP_XY_NOMIP));
|
||||
Colormaps.push_back(colormap);
|
||||
return colormap->Renderdev.bindIndex;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ class VulkanRenderDevice;
|
|||
class VkMaterial;
|
||||
class PPTextureInput;
|
||||
class VkPPRenderPassSetup;
|
||||
struct FSWColormap;
|
||||
|
||||
class VkDescriptorSetManager
|
||||
{
|
||||
|
|
@ -44,6 +45,8 @@ public:
|
|||
void UpdateBindlessDescriptorSet();
|
||||
int AddBindlessTextureIndex(VulkanImageView* imageview, VulkanSampler* sampler);
|
||||
|
||||
int GetSWColormapTextureIndex(FSWColormap* colormap);
|
||||
|
||||
private:
|
||||
void CreateLevelMeshLayout();
|
||||
void CreateRSBufferLayout();
|
||||
|
|
@ -115,6 +118,7 @@ private:
|
|||
} ZMinMax;
|
||||
|
||||
std::list<VkMaterial*> Materials;
|
||||
std::vector<FSWColormap*> Colormaps;
|
||||
|
||||
static const int MaxFixedSets = 100;
|
||||
static const int MaxBindlessTextures = 16536;
|
||||
|
|
|
|||
|
|
@ -464,6 +464,7 @@ void VkShaderManager::BuildDefinesBlock(FString &definesBlock, const char *defin
|
|||
definesBlock << "#define LIGHT_ATTENUATION_INVERSE_SQUARE ((uShaderKey1 & SK1_LIGHTATTENUATIONMODE) != 0)\n";
|
||||
|
||||
definesBlock << "#define FOGBALLS ((uShaderKey1 & SK1_FOGBALLS) != 0)\n";
|
||||
definesBlock << "#define PALETTEMODE ((uShaderKey1 & SK1_PALETTEMODE) != 0)\n";
|
||||
|
||||
definesBlock << "#define USE_DEPTHFADETHRESHOLD ((uShaderKey2 & SK2_USE_DEPTHFADETHRESHOLD) != 0)\n";
|
||||
definesBlock << "#define NOT_ALPHATEST_ONLY ((uShaderKey2 & SK2_ALPHATEST_ONLY) == 0)\n";
|
||||
|
|
|
|||
|
|
@ -105,7 +105,7 @@ public:
|
|||
uint64_t LightMode : 2; // LIGHTMODE_DEFAULT, LIGHTMODE_SOFTWARE, LIGHTMODE_VANILLA, LIGHTMODE_BUILD
|
||||
uint64_t LightBlendMode : 2; // LIGHT_BLEND_CLAMPED , LIGHT_BLEND_COLORED_CLAMP , LIGHT_BLEND_UNCLAMPED
|
||||
uint64_t LightAttenuationMode : 1; // LIGHT_ATTENUATION_LINEAR , LIGHT_ATTENUATION_INVERSE_SQUARE
|
||||
uint64_t Unused5: 1;
|
||||
uint64_t PaletteMode: 1;
|
||||
uint64_t FogBalls : 1; // FOGBALLS
|
||||
uint64_t NoFragmentShader : 1;
|
||||
uint64_t DepthFadeThreshold : 1;
|
||||
|
|
|
|||
|
|
@ -62,17 +62,25 @@ void VkHardwareTexture::Reset()
|
|||
}
|
||||
|
||||
mImage.Reset(fb);
|
||||
mPaletteImage.Reset(fb);
|
||||
mDepthStencil.Reset(fb);
|
||||
}
|
||||
}
|
||||
|
||||
VkTextureImage *VkHardwareTexture::GetImage(FTexture *tex, int translation, int flags)
|
||||
{
|
||||
if (!mImage.Image)
|
||||
if (flags & (CTF_Indexed | CTF_IndexedRedIsAlpha))
|
||||
{
|
||||
CreateImage(tex, translation, flags);
|
||||
if (!mPaletteImage.Image)
|
||||
CreateImage(&mPaletteImage, tex, translation, flags);
|
||||
return &mPaletteImage;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!mImage.Image)
|
||||
CreateImage(&mImage, tex, translation, flags);
|
||||
return &mImage;
|
||||
}
|
||||
return &mImage;
|
||||
}
|
||||
|
||||
VkTextureImage *VkHardwareTexture::GetDepthStencil(FTexture *tex)
|
||||
|
|
@ -105,7 +113,7 @@ VkTextureImage *VkHardwareTexture::GetDepthStencil(FTexture *tex)
|
|||
return &mDepthStencil;
|
||||
}
|
||||
|
||||
void VkHardwareTexture::CreateImage(FTexture *tex, int translation, int flags)
|
||||
void VkHardwareTexture::CreateImage(VkTextureImage* image, FTexture *tex, int translation, int flags)
|
||||
{
|
||||
if (!tex->isHardwareCanvas())
|
||||
{
|
||||
|
|
@ -115,7 +123,7 @@ void VkHardwareTexture::CreateImage(FTexture *tex, int translation, int flags)
|
|||
|
||||
FTextureBuffer texbuffer = tex->CreateTexBuffer(translation, flags | CTF_CheckOnly);
|
||||
bool indexed = flags & CTF_Indexed;
|
||||
CreateTexture(texbuffer.mWidth, texbuffer.mHeight, indexed ? 1 : 4, indexed ? VK_FORMAT_R8_UNORM : VK_FORMAT_B8G8R8A8_UNORM, texbuffer.mBuffer, !indexed);
|
||||
CreateTexture(image, texbuffer.mWidth, texbuffer.mHeight, indexed ? 1 : 4, indexed ? VK_FORMAT_R8_UNORM : VK_FORMAT_B8G8R8A8_UNORM, texbuffer.mBuffer, !indexed);
|
||||
|
||||
auto textureManager = fb->GetTextureManager();
|
||||
|
||||
|
|
@ -130,7 +138,7 @@ void VkHardwareTexture::CreateImage(FTexture *tex, int translation, int flags)
|
|||
// Upload the texture on the main thread, as long as the hwrenderer didn't destroy this hwtexture already.
|
||||
if (textureManager->CheckUploadID(uploadID))
|
||||
{
|
||||
UploadTexture(imagedata->mWidth, imagedata->mHeight, indexed ? 1 : 4, indexed ? VK_FORMAT_R8_UNORM : VK_FORMAT_B8G8R8A8_UNORM, imagedata->mBuffer, !indexed);
|
||||
UploadTexture(image, imagedata->mWidth, imagedata->mHeight, indexed ? 1 : 4, indexed ? VK_FORMAT_R8_UNORM : VK_FORMAT_B8G8R8A8_UNORM, imagedata->mBuffer, !indexed);
|
||||
}
|
||||
|
||||
});
|
||||
|
|
@ -140,7 +148,7 @@ void VkHardwareTexture::CreateImage(FTexture *tex, int translation, int flags)
|
|||
{
|
||||
FTextureBuffer texbuffer = tex->CreateTexBuffer(translation, flags | CTF_ProcessData);
|
||||
bool indexed = flags & CTF_Indexed;
|
||||
CreateTexture(texbuffer.mWidth, texbuffer.mHeight, indexed ? 1 : 4, indexed ? VK_FORMAT_R8_UNORM : VK_FORMAT_B8G8R8A8_UNORM, texbuffer.mBuffer, !indexed);
|
||||
CreateTexture(image, texbuffer.mWidth, texbuffer.mHeight, indexed ? 1 : 4, indexed ? VK_FORMAT_R8_UNORM : VK_FORMAT_B8G8R8A8_UNORM, texbuffer.mBuffer, !indexed);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
@ -149,25 +157,25 @@ void VkHardwareTexture::CreateImage(FTexture *tex, int translation, int flags)
|
|||
int w = tex->GetWidth();
|
||||
int h = tex->GetHeight();
|
||||
|
||||
mImage.Image = ImageBuilder()
|
||||
image->Image = ImageBuilder()
|
||||
.Format(format)
|
||||
.Size(w, h)
|
||||
.Usage(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT)
|
||||
.DebugName("VkHardwareTexture.mImage")
|
||||
.Create(fb->GetDevice());
|
||||
|
||||
mImage.View = ImageViewBuilder()
|
||||
.Image(mImage.Image.get(), format)
|
||||
image->View = ImageViewBuilder()
|
||||
.Image(image->Image.get(), format)
|
||||
.DebugName("VkHardwareTexture.mImageView")
|
||||
.Create(fb->GetDevice());
|
||||
|
||||
VkImageTransition()
|
||||
.AddImage(&mImage, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, true)
|
||||
.AddImage(image, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, true)
|
||||
.Execute(fb->GetCommands()->GetTransferCommands());
|
||||
}
|
||||
}
|
||||
|
||||
void VkHardwareTexture::CreateTexture(int w, int h, int pixelsize, VkFormat format, const void *pixels, bool mipmap)
|
||||
void VkHardwareTexture::CreateTexture(VkTextureImage* image, int w, int h, int pixelsize, VkFormat format, const void *pixels, bool mipmap)
|
||||
{
|
||||
if (w <= 0 || h <= 0)
|
||||
throw CVulkanError("Trying to create zero size texture");
|
||||
|
|
@ -189,22 +197,22 @@ void VkHardwareTexture::CreateTexture(int w, int h, int pixelsize, VkFormat form
|
|||
|
||||
stagingBuffer->Unmap();
|
||||
|
||||
mImage.Image = ImageBuilder()
|
||||
image->Image = ImageBuilder()
|
||||
.Format(format)
|
||||
.Size(w, h, !mipmap ? 1 : GetMipLevels(w, h))
|
||||
.Usage(VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT)
|
||||
.DebugName("VkHardwareTexture.mImage")
|
||||
.Create(fb->GetDevice());
|
||||
|
||||
mImage.View = ImageViewBuilder()
|
||||
.Image(mImage.Image.get(), format)
|
||||
image->View = ImageViewBuilder()
|
||||
.Image(image->Image.get(), format)
|
||||
.DebugName("VkHardwareTexture.mImageView")
|
||||
.Create(fb->GetDevice());
|
||||
|
||||
auto cmdbuffer = fb->GetCommands()->GetTransferCommands();
|
||||
|
||||
VkImageTransition()
|
||||
.AddImage(&mImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, true)
|
||||
.AddImage(image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, true)
|
||||
.Execute(cmdbuffer);
|
||||
|
||||
VkBufferImageCopy region = {};
|
||||
|
|
@ -213,9 +221,9 @@ void VkHardwareTexture::CreateTexture(int w, int h, int pixelsize, VkFormat form
|
|||
region.imageExtent.depth = 1;
|
||||
region.imageExtent.width = w;
|
||||
region.imageExtent.height = h;
|
||||
cmdbuffer->copyBufferToImage(stagingBuffer->buffer, mImage.Image->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion);
|
||||
cmdbuffer->copyBufferToImage(stagingBuffer->buffer, image->Image->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion);
|
||||
|
||||
if (mipmap) mImage.GenerateMipmaps(cmdbuffer);
|
||||
if (mipmap) image->GenerateMipmaps(cmdbuffer);
|
||||
|
||||
// If we queued more than 64 MB of data already: wait until the uploads finish before continuing
|
||||
fb->GetCommands()->TransferDeleteList->Add(std::move(stagingBuffer));
|
||||
|
|
@ -223,7 +231,7 @@ void VkHardwareTexture::CreateTexture(int w, int h, int pixelsize, VkFormat form
|
|||
fb->GetCommands()->WaitForCommands(false, true);
|
||||
}
|
||||
|
||||
void VkHardwareTexture::UploadTexture(int w, int h, int pixelsize, VkFormat format, const void* pixels, bool mipmap)
|
||||
void VkHardwareTexture::UploadTexture(VkTextureImage* image, int w, int h, int pixelsize, VkFormat format, const void* pixels, bool mipmap)
|
||||
{
|
||||
if (w <= 0 || h <= 0)
|
||||
throw CVulkanError("Trying to create zero size texture");
|
||||
|
|
@ -243,7 +251,7 @@ void VkHardwareTexture::UploadTexture(int w, int h, int pixelsize, VkFormat form
|
|||
auto cmdbuffer = fb->GetCommands()->GetTransferCommands();
|
||||
|
||||
VkImageTransition()
|
||||
.AddImage(&mImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, true)
|
||||
.AddImage(image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, true)
|
||||
.Execute(cmdbuffer);
|
||||
|
||||
VkBufferImageCopy region = {};
|
||||
|
|
@ -252,9 +260,9 @@ void VkHardwareTexture::UploadTexture(int w, int h, int pixelsize, VkFormat form
|
|||
region.imageExtent.depth = 1;
|
||||
region.imageExtent.width = w;
|
||||
region.imageExtent.height = h;
|
||||
cmdbuffer->copyBufferToImage(stagingBuffer->buffer, mImage.Image->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion);
|
||||
cmdbuffer->copyBufferToImage(stagingBuffer->buffer, image->Image->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion);
|
||||
|
||||
if (mipmap) mImage.GenerateMipmaps(cmdbuffer);
|
||||
if (mipmap) image->GenerateMipmaps(cmdbuffer);
|
||||
|
||||
// If we queued more than 64 MB of data already: wait until the uploads finish before continuing
|
||||
fb->GetCommands()->TransferDeleteList->Add(std::move(stagingBuffer));
|
||||
|
|
@ -323,7 +331,7 @@ unsigned int VkHardwareTexture::CreateTexture(unsigned char * buffer, int w, int
|
|||
{
|
||||
// CreateTexture is used by the software renderer to create a screen output but without any screen data.
|
||||
if (buffer)
|
||||
CreateTexture(w, h, mTexelsize, mTexelsize == 4 ? VK_FORMAT_B8G8R8A8_UNORM : VK_FORMAT_R8_UNORM, buffer, mipmap);
|
||||
CreateTexture(&mImage, w, h, mTexelsize, mTexelsize == 4 ? VK_FORMAT_B8G8R8A8_UNORM : VK_FORMAT_R8_UNORM, buffer, mipmap);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -409,9 +417,19 @@ VkMaterial::DescriptorEntry& VkMaterial::GetDescriptorEntry(const FMaterialState
|
|||
|
||||
clampmode = base->GetClampMode(clampmode);
|
||||
|
||||
int paletteFlags = 0;
|
||||
if (state.mPaletteMode)
|
||||
{
|
||||
paletteFlags |= CTF_Indexed; // To do: may need to implement CTF_IndexedRedIsAlpha too for the "style.Flags & STYLEF_RedIsAlpha" case
|
||||
|
||||
// We can't do linear filtering for indexed textures
|
||||
if (clampmode < CLAMP_NOFILTER)
|
||||
clampmode += CLAMP_NOFILTER;
|
||||
}
|
||||
|
||||
for (auto& set : mDescriptorSets)
|
||||
{
|
||||
if (set.clampmode == clampmode && set.remap == translationp && set.globalShaderAddr == globalShaderAddr) return set;
|
||||
if (set.clampmode == clampmode && set.remap == translationp && set.globalShaderAddr == globalShaderAddr && set.indexed == state.mPaletteMode) return set;
|
||||
}
|
||||
|
||||
auto globalshader = GetGlobalShader(globalShaderAddr);
|
||||
|
|
@ -421,7 +439,7 @@ VkMaterial::DescriptorEntry& VkMaterial::GetDescriptorEntry(const FMaterialState
|
|||
|
||||
MaterialLayerInfo *layer;
|
||||
auto systex = static_cast<VkHardwareTexture*>(GetLayer(0, state.mTranslation, &layer));
|
||||
auto systeximage = systex->GetImage(layer->layerTexture, state.mTranslation, layer->scaleFlags);
|
||||
auto systeximage = systex->GetImage(layer->layerTexture, state.mTranslation, layer->scaleFlags | paletteFlags);
|
||||
int bindlessIndex = descriptors->AddBindlessTextureIndex(systeximage->View.get(), fb->GetSamplerManager()->Get(GetLayerFilter(0), clampmode));
|
||||
|
||||
if (!(layer->scaleFlags & CTF_Indexed))
|
||||
|
|
@ -429,7 +447,7 @@ VkMaterial::DescriptorEntry& VkMaterial::GetDescriptorEntry(const FMaterialState
|
|||
for (int i = 1; i < numLayersMat; i++)
|
||||
{
|
||||
auto syslayer = static_cast<VkHardwareTexture*>(GetLayer(i, 0, &layer));
|
||||
auto syslayerimage = syslayer->GetImage(layer->layerTexture, 0, layer->scaleFlags);
|
||||
auto syslayerimage = syslayer->GetImage(layer->layerTexture, 0, layer->scaleFlags | paletteFlags);
|
||||
descriptors->AddBindlessTextureIndex(syslayerimage->View.get(), fb->GetSamplerManager()->Get(GetLayerFilter(i), clampmode));
|
||||
}
|
||||
|
||||
|
|
@ -441,7 +459,7 @@ VkMaterial::DescriptorEntry& VkMaterial::GetDescriptorEntry(const FMaterialState
|
|||
if (texture != nullptr)
|
||||
{
|
||||
VkHardwareTexture *tex = static_cast<VkHardwareTexture*>(texture.get()->GetHardwareTexture(0, 0));
|
||||
VkTextureImage *img = tex->GetImage(texture.get(), 0, 0);
|
||||
VkTextureImage *img = tex->GetImage(texture.get(), 0, paletteFlags);
|
||||
descriptors->AddBindlessTextureIndex(img->View.get(), fb->GetSamplerManager()->Get(globalshader->CustomShaderTextureSampling[i], clampmode));
|
||||
}
|
||||
i++;
|
||||
|
|
@ -453,11 +471,11 @@ VkMaterial::DescriptorEntry& VkMaterial::GetDescriptorEntry(const FMaterialState
|
|||
for (int i = 1; i < 3; i++)
|
||||
{
|
||||
auto syslayer = static_cast<VkHardwareTexture*>(GetLayer(i, translation, &layer));
|
||||
auto syslayerimage = syslayer->GetImage(layer->layerTexture, 0, layer->scaleFlags);
|
||||
auto syslayerimage = syslayer->GetImage(layer->layerTexture, 0, layer->scaleFlags | paletteFlags);
|
||||
descriptors->AddBindlessTextureIndex(syslayerimage->View.get(), fb->GetSamplerManager()->Get(GetLayerFilter(i), clampmode));
|
||||
}
|
||||
}
|
||||
|
||||
mDescriptorSets.emplace_back(clampmode, translationp, bindlessIndex, globalShaderAddr);
|
||||
mDescriptorSets.emplace_back(clampmode, translationp, bindlessIndex, globalShaderAddr, state.mPaletteMode);
|
||||
return mDescriptorSets.back();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,13 +46,13 @@ public:
|
|||
std::list<VkHardwareTexture*>::iterator it;
|
||||
|
||||
private:
|
||||
void CreateImage(FTexture *tex, int translation, int flags);
|
||||
void CreateImage(VkTextureImage* image, FTexture *tex, int translation, int flags);
|
||||
|
||||
void CreateTexture(int w, int h, int pixelsize, VkFormat format, const void *pixels, bool mipmap);
|
||||
void UploadTexture(int w, int h, int pixelsize, VkFormat format, const void* pixels, bool mipmap);
|
||||
void CreateTexture(VkTextureImage* image, int w, int h, int pixelsize, VkFormat format, const void *pixels, bool mipmap);
|
||||
void UploadTexture(VkTextureImage* image, int w, int h, int pixelsize, VkFormat format, const void* pixels, bool mipmap);
|
||||
static int GetMipLevels(int w, int h);
|
||||
|
||||
VkTextureImage mImage;
|
||||
VkTextureImage mImage, mPaletteImage;
|
||||
int mTexelsize = 4;
|
||||
|
||||
VkTextureImage mDepthStencil;
|
||||
|
|
@ -80,13 +80,15 @@ private:
|
|||
intptr_t remap;
|
||||
int bindlessIndex;
|
||||
GlobalShaderAddr globalShaderAddr;
|
||||
bool indexed;
|
||||
|
||||
DescriptorEntry(int cm, intptr_t f, int index, GlobalShaderAddr addr)
|
||||
DescriptorEntry(int cm, intptr_t f, int index, GlobalShaderAddr addr, bool paletteMode)
|
||||
{
|
||||
clampmode = cm;
|
||||
remap = f;
|
||||
bindlessIndex = index;
|
||||
globalShaderAddr = addr;
|
||||
indexed = paletteMode;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -26,11 +26,13 @@
|
|||
#include "vk_renderbuffers.h"
|
||||
#include "vulkan/vk_postprocess.h"
|
||||
#include "hw_cvars.h"
|
||||
#include "fcolormap.h"
|
||||
|
||||
VkTextureManager::VkTextureManager(VulkanRenderDevice* fb) : fb(fb)
|
||||
{
|
||||
CreateNullTexture();
|
||||
CreateBrdfLutTexture();
|
||||
CreateGamePalette();
|
||||
CreateShadowmap();
|
||||
CreateLightmap();
|
||||
CreateIrradiancemap();
|
||||
|
|
@ -231,6 +233,113 @@ void VkTextureManager::CreateBrdfLutTexture()
|
|||
.Execute(cmdbuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
|
||||
}
|
||||
|
||||
void VkTextureManager::CreateGamePalette()
|
||||
{
|
||||
GamePalette = ImageBuilder()
|
||||
.Format(VK_FORMAT_B8G8R8A8_UNORM)
|
||||
.Size(256, 1)
|
||||
.Usage(VK_IMAGE_USAGE_SAMPLED_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT)
|
||||
.DebugName("VkDescriptorSetManager.GamePalette")
|
||||
.Create(fb->GetDevice());
|
||||
|
||||
GamePaletteView = ImageViewBuilder()
|
||||
.Image(GamePalette.get(), VK_FORMAT_B8G8R8A8_UNORM)
|
||||
.DebugName("VkDescriptorSetManager.GamePaletteView")
|
||||
.Create(fb->GetDevice());
|
||||
}
|
||||
|
||||
void VkTextureManager::SetGamePalette()
|
||||
{
|
||||
auto cmdbuffer = fb->GetCommands()->GetTransferCommands();
|
||||
|
||||
PipelineBarrier()
|
||||
.AddImage(GamePalette.get(), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 0, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_ASPECT_COLOR_BIT)
|
||||
.Execute(cmdbuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
|
||||
|
||||
auto stagingBuffer = BufferBuilder()
|
||||
.Size(256 * 4)
|
||||
.Usage(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY)
|
||||
.DebugName("VkDescriptorSetManager.GamePaletteStagingBuffer")
|
||||
.Create(fb->GetDevice());
|
||||
|
||||
void* data = stagingBuffer->Map(0, 256 * 4);
|
||||
memcpy(data, GPalette.BaseColors, 256 * 4);
|
||||
stagingBuffer->Unmap();
|
||||
|
||||
VkBufferImageCopy region = {};
|
||||
region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
region.imageSubresource.layerCount = 1;
|
||||
region.imageExtent.depth = 1;
|
||||
region.imageExtent.width = 256;
|
||||
region.imageExtent.height = 1;
|
||||
cmdbuffer->copyBufferToImage(stagingBuffer->buffer, GamePalette->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion);
|
||||
|
||||
fb->GetCommands()->TransferDeleteList->Add(std::move(stagingBuffer));
|
||||
|
||||
PipelineBarrier()
|
||||
.AddImage(GamePalette.get(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT, VK_IMAGE_ASPECT_COLOR_BIT)
|
||||
.Execute(cmdbuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
|
||||
}
|
||||
|
||||
VulkanImageView* VkTextureManager::GetSWColormapView(FSWColormap* colormap)
|
||||
{
|
||||
if (colormap->Renderdev.textureIndex != -1)
|
||||
return Colormaps[colormap->Renderdev.textureIndex].View.get();
|
||||
|
||||
SWColormapTexture tex;
|
||||
|
||||
tex.Texture = ImageBuilder()
|
||||
.Format(VK_FORMAT_B8G8R8A8_UNORM)
|
||||
.Size(256, 32)
|
||||
.Usage(VK_IMAGE_USAGE_SAMPLED_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT)
|
||||
.DebugName("VkDescriptorSetManager.SWColormap")
|
||||
.Create(fb->GetDevice());
|
||||
|
||||
tex.View = ImageViewBuilder()
|
||||
.Image(tex.Texture.get(), VK_FORMAT_B8G8R8A8_UNORM)
|
||||
.DebugName("VkDescriptorSetManager.SWColormapView")
|
||||
.Create(fb->GetDevice());
|
||||
|
||||
auto cmdbuffer = fb->GetCommands()->GetTransferCommands();
|
||||
|
||||
PipelineBarrier()
|
||||
.AddImage(tex.Texture.get(), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 0, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_ASPECT_COLOR_BIT)
|
||||
.Execute(cmdbuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
|
||||
|
||||
auto stagingBuffer = BufferBuilder()
|
||||
.Size(256 * 32 * sizeof(uint32_t))
|
||||
.Usage(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY)
|
||||
.DebugName("VkDescriptorSetManager.SWColormapStagingBuffer")
|
||||
.Create(fb->GetDevice());
|
||||
|
||||
const uint8_t* src = colormap->Maps;
|
||||
uint32_t* data = static_cast<uint32_t*>(stagingBuffer->Map(0, 256 * 32 * sizeof(uint32_t)));
|
||||
for (int i = 0; i < 256 * 32; i++)
|
||||
{
|
||||
data[i] = GPalette.BaseColors[src[i]].d;
|
||||
}
|
||||
stagingBuffer->Unmap();
|
||||
|
||||
VkBufferImageCopy region = {};
|
||||
region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
region.imageSubresource.layerCount = 1;
|
||||
region.imageExtent.depth = 1;
|
||||
region.imageExtent.width = 256;
|
||||
region.imageExtent.height = 32;
|
||||
cmdbuffer->copyBufferToImage(stagingBuffer->buffer, tex.Texture->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion);
|
||||
|
||||
fb->GetCommands()->TransferDeleteList->Add(std::move(stagingBuffer));
|
||||
|
||||
PipelineBarrier()
|
||||
.AddImage(tex.Texture.get(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT, VK_IMAGE_ASPECT_COLOR_BIT)
|
||||
.Execute(cmdbuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
|
||||
|
||||
colormap->Renderdev.textureIndex = Colormaps.size();
|
||||
Colormaps.push_back(std::move(tex));
|
||||
|
||||
return Colormaps[colormap->Renderdev.textureIndex].View.get();
|
||||
}
|
||||
|
||||
void VkTextureManager::CreateShadowmap()
|
||||
{
|
||||
Shadowmap.Image = ImageBuilder()
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ class VkPPTexture;
|
|||
class VkTextureImage;
|
||||
enum class PPTextureType;
|
||||
class PPTexture;
|
||||
struct FSWColormap;
|
||||
|
||||
class VkTextureManager
|
||||
{
|
||||
|
|
@ -32,6 +33,8 @@ public:
|
|||
void CreatePrefiltermap(int size, int count, const TArray<uint16_t>& data);
|
||||
void DownloadLightmap(int arrayIndex, uint16_t* buffer);
|
||||
|
||||
void SetGamePalette();
|
||||
|
||||
VkTextureImage* GetTexture(const PPTextureType& type, PPTexture* tex);
|
||||
VkFormat GetTextureFormat(PPTexture* texture);
|
||||
|
||||
|
|
@ -47,6 +50,11 @@ public:
|
|||
VulkanImage* GetBrdfLutTexture() { return BrdfLutTexture.get(); }
|
||||
VulkanImageView* GetBrdfLutTextureView() { return BrdfLutTextureView.get(); }
|
||||
|
||||
VulkanImage* GetGamePalette() { return GamePalette.get(); }
|
||||
VulkanImageView* GetGamePaletteView() { return GamePaletteView.get(); }
|
||||
|
||||
VulkanImageView* GetSWColormapView(FSWColormap* colormap);
|
||||
|
||||
int GetHWTextureCount() { return (int)Textures.size(); }
|
||||
|
||||
VkTextureImage Shadowmap;
|
||||
|
|
@ -70,6 +78,7 @@ public:
|
|||
private:
|
||||
void CreateNullTexture();
|
||||
void CreateBrdfLutTexture();
|
||||
void CreateGamePalette();
|
||||
void CreateShadowmap();
|
||||
void CreateLightmap();
|
||||
void CreateIrradiancemap();
|
||||
|
|
@ -92,6 +101,16 @@ private:
|
|||
std::unique_ptr<VulkanImage> BrdfLutTexture;
|
||||
std::unique_ptr<VulkanImageView> BrdfLutTextureView;
|
||||
|
||||
std::unique_ptr<VulkanImage> GamePalette;
|
||||
std::unique_ptr<VulkanImageView> GamePaletteView;
|
||||
|
||||
struct SWColormapTexture
|
||||
{
|
||||
std::unique_ptr<VulkanImage> Texture;
|
||||
std::unique_ptr<VulkanImageView> View;
|
||||
};
|
||||
std::vector<SWColormapTexture> Colormaps;
|
||||
|
||||
int NextUploadID = 1;
|
||||
std::unordered_map<int, VkHardwareTexture*> PendingUploads;
|
||||
|
||||
|
|
|
|||
|
|
@ -844,7 +844,7 @@ void VkLevelMeshUploader::UploadSurfaces()
|
|||
if (surface->Texture)
|
||||
{
|
||||
auto mat = FMaterial::ValidateTexture(surface->Texture, 0);
|
||||
info.TextureIndex = Mesh->fb->GetBindlessTextureIndex(mat, CLAMP_NONE, 0);
|
||||
info.TextureIndex = Mesh->fb->GetBindlessTextureIndex(mat, CLAMP_NONE, 0, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -873,7 +873,7 @@ void VkLevelMeshUploader::UploadUniforms()
|
|||
auto source = material.mMaterial->Source();
|
||||
surfaceUniforms.uSpecularMaterial = { source->GetGlossiness(), source->GetSpecularLevel() };
|
||||
surfaceUniforms.uDepthFadeThreshold = source->GetDepthFadeThreshold();
|
||||
surfaceUniforms.uTextureIndex = Mesh->fb->GetBindlessTextureIndex(material.mMaterial, material.mClampMode, material.mTranslation);
|
||||
surfaceUniforms.uTextureIndex = Mesh->fb->GetBindlessTextureIndex(material.mMaterial, material.mClampMode, material.mTranslation, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
|
|
@ -482,6 +482,8 @@ void VulkanRenderDevice::UpdatePalette()
|
|||
{
|
||||
if (mPostprocess)
|
||||
mPostprocess->ClearTonemapPalette();
|
||||
|
||||
mTextureManager->SetGamePalette();
|
||||
}
|
||||
|
||||
FTexture *VulkanRenderDevice::WipeStartScreen()
|
||||
|
|
@ -748,7 +750,7 @@ void VulkanRenderDevice::DownloadLightmap(int arrayIndex, uint16_t* buffer)
|
|||
mTextureManager->DownloadLightmap(arrayIndex, buffer);
|
||||
}
|
||||
|
||||
int VulkanRenderDevice::GetBindlessTextureIndex(FMaterial* material, int clampmode, int translation)
|
||||
int VulkanRenderDevice::GetBindlessTextureIndex(FMaterial* material, int clampmode, int translation, bool paletteMode)
|
||||
{
|
||||
GlobalShaderAddr addr;
|
||||
auto globalshader = GetGlobalShader(material->GetShaderIndex(), nullptr, addr);
|
||||
|
|
@ -757,6 +759,7 @@ int VulkanRenderDevice::GetBindlessTextureIndex(FMaterial* material, int clampmo
|
|||
materialState.mMaterial = material;
|
||||
materialState.mClampMode = clampmode;
|
||||
materialState.mTranslation = translation;
|
||||
materialState.mPaletteMode = paletteMode;
|
||||
|
||||
if(addr.type == 1 && *globalshader)
|
||||
{ // handle per-map global shaders
|
||||
|
|
|
|||
|
|
@ -95,7 +95,7 @@ public:
|
|||
|
||||
void WaitForCommands(bool finish) override;
|
||||
|
||||
int GetBindlessTextureIndex(FMaterial* material, int clampmode, int translation) override;
|
||||
int GetBindlessTextureIndex(FMaterial* material, int clampmode, int translation, bool paletteMode) override;
|
||||
|
||||
int GetLevelMeshPipelineID(const MeshApplyData& applyData, const SurfaceUniforms& surfaceUniforms, const FMaterialState& material) override;
|
||||
void DownloadLightmap(int arrayIndex, uint16_t* buffer) override;
|
||||
|
|
|
|||
|
|
@ -343,6 +343,8 @@ void VkRenderState::ApplyRenderPass(int dt)
|
|||
pipelineKey.ShaderKey.LightBlendMode = (level.info ? static_cast<int>(level.info->lightblendmode) : 0);
|
||||
pipelineKey.ShaderKey.LightAttenuationMode = (level.info ? static_cast<int>(level.info->lightattenuationmode) : 0);
|
||||
|
||||
pipelineKey.ShaderKey.PaletteMode = mPaletteMode;
|
||||
|
||||
// Is this the one we already have?
|
||||
bool inRenderPass = mCommandBuffer;
|
||||
bool changingPipeline = (!inRenderPass) || (pipelineKey != mPipelineKey);
|
||||
|
|
@ -441,6 +443,21 @@ void VkRenderState::ApplySurfaceUniforms()
|
|||
else
|
||||
mSurfaceUniforms.timer = 0.0f;
|
||||
|
||||
if (mMaterial.mPaletteMode != mPaletteMode)
|
||||
{
|
||||
mMaterial.mPaletteMode = mPaletteMode;
|
||||
mMaterial.mChanged = true;
|
||||
}
|
||||
|
||||
if (mPaletteMode && mSWColormap)
|
||||
{
|
||||
mSurfaceUniforms.uColormapIndex = fb->GetDescriptorSetManager()->GetSWColormapTextureIndex(mSWColormap);
|
||||
}
|
||||
else
|
||||
{
|
||||
mSurfaceUniforms.uColormapIndex = 0;
|
||||
}
|
||||
|
||||
if (mMaterial.mChanged)
|
||||
{
|
||||
if (mMaterial.mMaterial)
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ enum ECreateTexBufferFlags
|
|||
CTF_Indexed = 4, // Tell the backend to create an indexed 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_ProcessData = 16, // run postprocessing on the generated buffer. This is only needed when using the data for a hardware texture.
|
||||
CTF_IndexedRedIsAlpha = 32, // Tell the backend to create an indexed alpha texture.
|
||||
};
|
||||
|
||||
class FHardwareTextureContainer
|
||||
|
|
|
|||
|
|
@ -332,12 +332,13 @@ FTextureBuffer FTexture::CreateTexBuffer(int translation, int flags)
|
|||
std::unique_lock lock(mutex);
|
||||
|
||||
FTextureBuffer result;
|
||||
if (flags & CTF_Indexed)
|
||||
if (flags & (CTF_Indexed | CTF_IndexedRedIsAlpha))
|
||||
{
|
||||
// Indexed textures will never be translated and never be scaled.
|
||||
int w = GetWidth(), h = GetHeight();
|
||||
|
||||
auto store = Get8BitPixels(false);
|
||||
bool alpha = !!(flags & CTF_IndexedRedIsAlpha);
|
||||
auto store = Get8BitPixels(alpha);
|
||||
const uint8_t* p = store.Data();
|
||||
|
||||
result.mBuffer = new uint8_t[w * h];
|
||||
|
|
|
|||
|
|
@ -241,9 +241,9 @@ CUSTOM_CVAR(Int, vid_rendermode, 4, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOIN
|
|||
{
|
||||
self = 4;
|
||||
}
|
||||
else if (self == 2 || self == 3)
|
||||
else if (self == 3)
|
||||
{
|
||||
self = self - 2; // softpoly to software
|
||||
self = 4; // map old softpoly truecolor to hwrenderer
|
||||
}
|
||||
|
||||
if (usergame)
|
||||
|
|
@ -405,7 +405,7 @@ void D_Render(std::function<void()> action, bool interpolate)
|
|||
for (auto Level : AllLevels())
|
||||
{
|
||||
// Check for the presence of dynamic lights at the start of the frame once.
|
||||
if ((gl_lights && vid_rendermode == 4) || (r_dynlights && vid_rendermode != 4) || Level->lightmaps)
|
||||
if ((gl_lights && V_IsHardwareRenderer()) || (r_dynlights && V_IsSoftwareRenderer()) || Level->lightmaps)
|
||||
{
|
||||
Level->HasDynamicLights = Level->lights || Level->lightmaps;
|
||||
}
|
||||
|
|
@ -987,7 +987,7 @@ void D_Display ()
|
|||
// No wipes when in a stereo3D VR mode
|
||||
else if (gamestate != wipegamestate && gamestate != GS_FULLCONSOLE && gamestate != GS_TITLELEVEL)
|
||||
{
|
||||
if (vr_mode == 0 || vid_rendermode != 4)
|
||||
if (vr_mode == 0 || V_IsSoftwareRenderer())
|
||||
{
|
||||
// save the current screen if about to wipe
|
||||
wipestart = screen->WipeStartScreen();
|
||||
|
|
@ -3320,11 +3320,8 @@ static int D_InitGame(const FIWADInfo* iwad_info, std::vector<std::string>& allw
|
|||
screen->CompileNextShader();
|
||||
if (StartScreen != nullptr) StartScreen->Render();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Update screen palette when restarting
|
||||
screen->UpdatePalette();
|
||||
}
|
||||
|
||||
screen->UpdatePalette();
|
||||
|
||||
// Base systems have been inited; enable cvar callbacks
|
||||
FBaseCVar::EnableCallbacks ();
|
||||
|
|
|
|||
|
|
@ -161,7 +161,12 @@ constexpr int vid_rendermode = 4;
|
|||
|
||||
inline bool V_IsHardwareRenderer()
|
||||
{
|
||||
return vid_rendermode == 4;
|
||||
return vid_rendermode == 4 || vid_rendermode == 2;
|
||||
}
|
||||
|
||||
inline bool V_IsSoftwareRenderer()
|
||||
{
|
||||
return !V_IsHardwareRenderer();
|
||||
}
|
||||
|
||||
inline bool V_IsTrueColor()
|
||||
|
|
|
|||
|
|
@ -111,7 +111,7 @@ void FThinkerCollection::RunThinkers(FLevelLocals *Level)
|
|||
ThinkCycles.Clock();
|
||||
|
||||
bool dolights;
|
||||
if ((gl_lights && vid_rendermode == 4) || (r_dynlights && vid_rendermode != 4) || Level->lightmaps)
|
||||
if ((gl_lights && V_IsHardwareRenderer()) || (r_dynlights && V_IsSoftwareRenderer()) || Level->lightmaps)
|
||||
{
|
||||
dolights = true;// Level->lights || (Level->flags3 & LEVEL3_LIGHTCREATED) || Level->lightmaps;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,6 +48,8 @@
|
|||
#include "actorinlines.h"
|
||||
#include "g_levellocals.h"
|
||||
#include "hw_lighting.h"
|
||||
#include "d_main.h"
|
||||
#include "swrenderer/r_swcolormaps.h"
|
||||
|
||||
EXTERN_CVAR(Float, r_visibility)
|
||||
EXTERN_CVAR(Int, lm_background_updates);
|
||||
|
|
@ -783,6 +785,15 @@ void HWDrawInfo::RenderScene(FRenderState &state)
|
|||
UpdateLightmaps();
|
||||
|
||||
state.SetLightMode((int)lightmode);
|
||||
|
||||
if (!V_IsTrueColor())
|
||||
{
|
||||
state.SetPaletteMode(!V_IsTrueColor());
|
||||
|
||||
FColormap cm;
|
||||
cm.Clear();
|
||||
state.SetSWColormap(GetColorTable(cm));
|
||||
}
|
||||
|
||||
state.SetDepthMask(true);
|
||||
|
||||
|
|
@ -829,6 +840,8 @@ void HWDrawInfo::RenderScene(FRenderState &state)
|
|||
state.SetDepthFunc(DF_LEqual);
|
||||
DrawDecals(state, Decals[0]);
|
||||
|
||||
state.SetPaletteMode(false);
|
||||
|
||||
RenderAll.Unclock();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,14 +3,6 @@
|
|||
|
||||
#include "g_levellocals.h"
|
||||
|
||||
struct FSWColormap
|
||||
{
|
||||
uint8_t *Maps = nullptr;
|
||||
PalEntry Color = 0xffffffff;
|
||||
PalEntry Fade = 0xff000000;
|
||||
int Desaturate = 0;
|
||||
};
|
||||
|
||||
struct FDynamicColormap : FSWColormap
|
||||
{
|
||||
void ChangeFade (PalEntry fadecolor);
|
||||
|
|
|
|||
|
|
@ -114,10 +114,10 @@ struct SurfaceUniforms
|
|||
|
||||
float uAlphaThreshold;
|
||||
int uTextureIndex;
|
||||
float uDepthFadeThreshold;
|
||||
int uColormapIndex;
|
||||
int uLightProbeIndex;
|
||||
vec3 uActorCenter;
|
||||
float padding2;
|
||||
float uDepthFadeThreshold;
|
||||
};
|
||||
|
||||
struct SurfaceLightUniforms
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@
|
|||
#define uLightDist data[uDataIndex].uLightDist
|
||||
#define uAlphaThreshold data[uDataIndex].uAlphaThreshold
|
||||
#define uTextureIndex data[uDataIndex].uTextureIndex
|
||||
#define uColormapIndex data[uDataIndex].uColormapIndex
|
||||
#define uDepthFadeThreshold data[uDataIndex].uDepthFadeThreshold
|
||||
#define uActorCenter data[uDataIndex].uActorCenter
|
||||
#define uLightProbeIndex data[uDataIndex].uLightProbeIndex
|
||||
|
|
|
|||
|
|
@ -22,75 +22,96 @@
|
|||
|
||||
vec4 getLightColor(Material material)
|
||||
{
|
||||
vec4 color;
|
||||
if (LIGHTMODE_DEFAULT)
|
||||
color = Lightmode_Default();
|
||||
else if (LIGHTMODE_SOFTWARE)
|
||||
color = Lightmode_Software();
|
||||
else if (LIGHTMODE_VANILLA)
|
||||
color = Lightmode_Vanilla();
|
||||
else if (LIGHTMODE_BUILD)
|
||||
color = Lightmode_Build();
|
||||
|
||||
//
|
||||
// handle glowing walls
|
||||
//
|
||||
if (uGlowTopColor.a > 0.0 && glowdist.x < uGlowTopColor.a)
|
||||
if (PALETTEMODE)
|
||||
{
|
||||
color.rgb += desaturate(uGlowTopColor * (1.0 - glowdist.x / uGlowTopColor.a)).rgb;
|
||||
}
|
||||
if (uGlowBottomColor.a > 0.0 && glowdist.y < uGlowBottomColor.a)
|
||||
{
|
||||
color.rgb += desaturate(uGlowBottomColor * (1.0 - glowdist.y / uGlowBottomColor.a)).rgb;
|
||||
}
|
||||
color = min(color, 1.0);
|
||||
int color = int(material.Base.r * 255.0 + 0.5);
|
||||
|
||||
// these cannot be safely applied by the legacy format where the implementation cannot guarantee that the values are set.
|
||||
#if !defined LEGACY_USER_SHADER && !defined NO_LAYERS
|
||||
//
|
||||
// apply glow
|
||||
//
|
||||
color.rgb = mix(color.rgb, material.Glow.rgb, material.Glow.a);
|
||||
|
||||
//
|
||||
// apply brightmaps
|
||||
//
|
||||
color.rgb = min(color.rgb + material.Bright.rgb, 1.0);
|
||||
#endif
|
||||
|
||||
//
|
||||
// apply lightmaps
|
||||
//
|
||||
if (vLightmap.z >= 0.0)
|
||||
{
|
||||
color.rgb += texture(LightMap, vLightmap).rgb;
|
||||
}
|
||||
|
||||
//
|
||||
// apply dynamic lights
|
||||
//
|
||||
vec4 frag = vec4(ProcessMaterialLight(material, color.rgb), material.Base.a * vColor.a);
|
||||
|
||||
//
|
||||
// colored fog
|
||||
//
|
||||
if (FOG_AFTER_LIGHTS)
|
||||
{
|
||||
// calculate fog factor
|
||||
float fogdist;
|
||||
if (FOG_RADIAL)
|
||||
fogdist = max(16.0, distance(pixelpos.xyz, uCameraPos.xyz));
|
||||
// z is the depth in view space, positive going into the screen
|
||||
float z;
|
||||
if (SWLIGHT_RADIAL)
|
||||
z = distance(pixelpos.xyz, uCameraPos.xyz);
|
||||
else
|
||||
fogdist = max(16.0, pixelpos.w);
|
||||
float fogfactor = exp2 (uFogDensity * fogdist);
|
||||
z = pixelpos.w;
|
||||
|
||||
frag = vec4(mix(uFogColor.rgb, frag.rgb, fogfactor), frag.a);
|
||||
float L = uLightLevel * 255.0;
|
||||
float vis = min(uGlobVis / z, 24.0 / 32.0);
|
||||
float shade = 2.0 - (L + 12.0) / 128.0;
|
||||
int light = max(int((shade - vis) * 32), 0);
|
||||
|
||||
return vec4(texelFetch(textures[uColormapIndex], ivec2(color, light), 0).rgb, 1.0);
|
||||
}
|
||||
else
|
||||
{
|
||||
vec4 color;
|
||||
if (LIGHTMODE_DEFAULT)
|
||||
color = Lightmode_Default();
|
||||
else if (LIGHTMODE_SOFTWARE)
|
||||
color = Lightmode_Software();
|
||||
else if (LIGHTMODE_VANILLA)
|
||||
color = Lightmode_Vanilla();
|
||||
else if (LIGHTMODE_BUILD)
|
||||
color = Lightmode_Build();
|
||||
|
||||
if (FOGBALLS)
|
||||
frag = ProcessFogBalls(frag);
|
||||
//
|
||||
// handle glowing walls
|
||||
//
|
||||
if (uGlowTopColor.a > 0.0 && glowdist.x < uGlowTopColor.a)
|
||||
{
|
||||
color.rgb += desaturate(uGlowTopColor * (1.0 - glowdist.x / uGlowTopColor.a)).rgb;
|
||||
}
|
||||
if (uGlowBottomColor.a > 0.0 && glowdist.y < uGlowBottomColor.a)
|
||||
{
|
||||
color.rgb += desaturate(uGlowBottomColor * (1.0 - glowdist.y / uGlowBottomColor.a)).rgb;
|
||||
}
|
||||
color = min(color, 1.0);
|
||||
|
||||
return frag;
|
||||
// these cannot be safely applied by the legacy format where the implementation cannot guarantee that the values are set.
|
||||
#if !defined LEGACY_USER_SHADER && !defined NO_LAYERS
|
||||
//
|
||||
// apply glow
|
||||
//
|
||||
color.rgb = mix(color.rgb, material.Glow.rgb, material.Glow.a);
|
||||
|
||||
//
|
||||
// apply brightmaps
|
||||
//
|
||||
color.rgb = min(color.rgb + material.Bright.rgb, 1.0);
|
||||
#endif
|
||||
|
||||
//
|
||||
// apply lightmaps
|
||||
//
|
||||
if (vLightmap.z >= 0.0)
|
||||
{
|
||||
color.rgb += texture(LightMap, vLightmap).rgb;
|
||||
}
|
||||
|
||||
//
|
||||
// apply dynamic lights
|
||||
//
|
||||
vec4 frag = vec4(ProcessMaterialLight(material, color.rgb), material.Base.a * vColor.a);
|
||||
|
||||
//
|
||||
// colored fog
|
||||
//
|
||||
if (FOG_AFTER_LIGHTS)
|
||||
{
|
||||
// calculate fog factor
|
||||
float fogdist;
|
||||
if (FOG_RADIAL)
|
||||
fogdist = max(16.0, distance(pixelpos.xyz, uCameraPos.xyz));
|
||||
else
|
||||
fogdist = max(16.0, pixelpos.w);
|
||||
float fogfactor = exp2 (uFogDensity * fogdist);
|
||||
|
||||
frag = vec4(mix(uFogColor.rgb, frag.rgb, fogfactor), frag.a);
|
||||
}
|
||||
|
||||
if (FOGBALLS)
|
||||
frag = ProcessFogBalls(frag);
|
||||
|
||||
return frag;
|
||||
}
|
||||
}
|
||||
|
||||
// The color of the fragment if it is fully occluded by ambient lighting
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@
|
|||
#define SK1_LIGHT_LIGHT_BLEND_COLORED_CLAMP 1
|
||||
#define SK1_LIGHT_BLEND_UNCLAMPED 2
|
||||
#define SK1_LIGHTATTENUATIONMODE (1 << 29)
|
||||
//#define SK1_USE_LEVELMESH (1 << 30)
|
||||
#define SK1_PALETTEMODE (1 << 30)
|
||||
#define SK1_FOGBALLS (1 << 31)
|
||||
|
||||
//#define SK2_NOFRAGMENTSHADER (1 << 0)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue