1
0
forked from mirrors/0ad

Adds PBR output texture to PostProc

This commit is contained in:
Vladislav Belov
2026-04-29 19:25:14 +02:00
parent 25df2d8a02
commit a7967d4ad9
8 changed files with 177 additions and 47 deletions
+2
View File
@@ -97,6 +97,7 @@ X(color)
X(colorAdd) X(colorAdd)
X(colorMul) X(colorMul)
X(compute_rcas) X(compute_rcas)
X(compute_resolve_pbr)
X(compute_skinning) X(compute_skinning)
X(compute_upscale_fsr) X(compute_upscale_fsr)
X(debug_line) X(debug_line)
@@ -104,6 +105,7 @@ X(debug_overlay)
X(delta) X(delta)
X(depthTex) X(depthTex)
X(dummy) X(dummy)
X(exposure)
X(foamTex) X(foamTex)
X(fogColor) X(fogColor)
X(fogParams) X(fogParams)
+140 -42
View File
@@ -128,6 +128,7 @@ void CPostprocManager::Cleanup()
m_PingFramebuffer.reset(); m_PingFramebuffer.reset();
m_PongFramebuffer.reset(); m_PongFramebuffer.reset();
m_PBROutputTexture.reset();
m_ColorTex1.reset(); m_ColorTex1.reset();
m_ColorTex2.reset(); m_ColorTex2.reset();
m_DepthTex.reset(); m_DepthTex.reset();
@@ -147,6 +148,9 @@ void CPostprocManager::Initialize()
if (m_IsInitialized) if (m_IsInitialized)
return; return;
if (g_ConfigDB.Get("pbr", false))
InitializePBR();
const std::array<Renderer::Backend::SVertexAttributeFormat, 2> attributes{{ const std::array<Renderer::Backend::SVertexAttributeFormat, 2> attributes{{
{Renderer::Backend::VertexAttributeStream::POSITION, {Renderer::Backend::VertexAttributeStream::POSITION,
Renderer::Backend::Format::R32G32_SFLOAT, 0, sizeof(float) * 2, Renderer::Backend::Format::R32G32_SFLOAT, 0, sizeof(float) * 2,
@@ -183,6 +187,40 @@ void CPostprocManager::Initialize()
m_DownscaleComputeTech = g_Renderer.GetShaderManager().LoadEffect(CStrIntern("compute_downscale")); m_DownscaleComputeTech = g_Renderer.GetShaderManager().LoadEffect(CStrIntern("compute_downscale"));
} }
void CPostprocManager::InitializePBR()
{
const bool PBRSupported{
m_Device->GetCapabilities().computeShaders &&
m_Device->IsFramebufferFormatSupported(Renderer::Backend::Format::R16G16B16A16_SFLOAT)};
if (!PBRSupported)
{
m_PBREnabled = false;
LOGWARNING("PBR is unsupported for the current renderer backend");
return;
}
m_FramebufferColorFormat = Renderer::Backend::Format::R16G16B16A16_SFLOAT;
const std::string framebufferFormatName{g_ConfigDB.Get("pbr.framebufferformat", std::string{})};
if (framebufferFormatName == "rgba32")
{
if (m_Device->IsFramebufferFormatSupported(Renderer::Backend::Format::R32G32B32A32_SFLOAT))
m_FramebufferColorFormat = Renderer::Backend::Format::R32G32B32A32_SFLOAT;
else
LOGWARNING("%s is unsupported", framebufferFormatName);
}
else if (framebufferFormatName == "r11g11b10")
{
if (m_Device->IsFramebufferFormatSupported(Renderer::Backend::Format::B10G11R11_UFLOAT))
m_FramebufferColorFormat = Renderer::Backend::Format::B10G11R11_UFLOAT;
else
LOGWARNING("%s is unsupported", framebufferFormatName);
}
m_ResolvePBRComputeTech = g_Renderer.GetShaderManager().LoadEffect(str_compute_resolve_pbr);
if (m_ResolvePBRComputeTech)
m_PBREnabled = true;
}
void CPostprocManager::Resize() void CPostprocManager::Resize()
{ {
RecalculateSize(g_Renderer.GetWidth(), g_Renderer.GetHeight()); RecalculateSize(g_Renderer.GetWidth(), g_Renderer.GetHeight());
@@ -196,21 +234,33 @@ void CPostprocManager::RecreateBuffers()
{ {
Cleanup(); Cleanup();
#define GEN_BUFFER_RGBA(name, w, h) \ const auto defaultSampler{
name = m_Device->CreateTexture2D( \ Renderer::Backend::Sampler::MakeDefaultSampler(
"PostProc" #name, \ Renderer::Backend::Sampler::Filter::LINEAR,
Renderer::Backend::ITexture::Usage::SAMPLED | \ Renderer::Backend::Sampler::AddressMode::CLAMP_TO_EDGE)};
Renderer::Backend::ITexture::Usage::COLOR_ATTACHMENT | \ const uint32_t colorTextureUsage{
Renderer::Backend::ITexture::Usage::TRANSFER_SRC | \ Renderer::Backend::ITexture::Usage::SAMPLED |
Renderer::Backend::ITexture::Usage::TRANSFER_DST, \ Renderer::Backend::ITexture::Usage::COLOR_ATTACHMENT |
Renderer::Backend::Format::R8G8B8A8_UNORM, w, h, \ Renderer::Backend::ITexture::Usage::TRANSFER_SRC |
Renderer::Backend::Sampler::MakeDefaultSampler( \ Renderer::Backend::ITexture::Usage::TRANSFER_DST};
Renderer::Backend::Sampler::Filter::LINEAR, \
Renderer::Backend::Sampler::AddressMode::CLAMP_TO_EDGE)); if (m_PBREnabled)
{
m_PBROutputTexture = m_Device->CreateTexture2D(
"PostProcPBROutput", colorTextureUsage,
m_FramebufferColorFormat,
m_Width, m_Height, defaultSampler);
}
// Two fullscreen ping-pong textures. // Two fullscreen ping-pong textures.
GEN_BUFFER_RGBA(m_ColorTex1, m_Width, m_Height); m_ColorTex1 = m_Device->CreateTexture2D(
GEN_BUFFER_RGBA(m_ColorTex2, m_Width, m_Height); "PostProcColor1", colorTextureUsage | (m_PBREnabled ? Renderer::Backend::ITexture::Usage::STORAGE : 0),
Renderer::Backend::Format::R8G8B8A8_UNORM,
m_Width, m_Height, defaultSampler);
m_ColorTex2 = m_Device->CreateTexture2D(
"PostProcColor2", colorTextureUsage | (m_PBREnabled ? Renderer::Backend::ITexture::Usage::STORAGE : 0),
Renderer::Backend::Format::R8G8B8A8_UNORM,
m_Width, m_Height, defaultSampler);
if (m_UnscaledWidth != m_Width && m_Device->GetCapabilities().computeShaders) if (m_UnscaledWidth != m_Width && m_Device->GetCapabilities().computeShaders)
{ {
@@ -257,7 +307,10 @@ void CPostprocManager::RecreateBuffers()
{ {
for (BlurScale::Step& step : scale.steps) for (BlurScale::Step& step : scale.steps)
{ {
GEN_BUFFER_RGBA(step.texture, width, height); step.texture = m_Device->CreateTexture2D(
"PostProcBlurStep", colorTextureUsage,
Renderer::Backend::Format::R8G8B8A8_UNORM,
width, height, defaultSampler);
Renderer::Backend::SColorAttachment colorAttachment{}; Renderer::Backend::SColorAttachment colorAttachment{};
colorAttachment.texture = step.texture.get(); colorAttachment.texture = step.texture.get();
colorAttachment.loadOp = Renderer::Backend::AttachmentLoadOp::LOAD; colorAttachment.loadOp = Renderer::Backend::AttachmentLoadOp::LOAD;
@@ -270,8 +323,6 @@ void CPostprocManager::RecreateBuffers()
height = std::max(1u, height / 2); height = std::max(1u, height / 2);
} }
#undef GEN_BUFFER_RGBA
// Allocate the Depth/Stencil texture. // Allocate the Depth/Stencil texture.
m_DepthTex = m_Device->CreateTexture2D("PostProcDepthTexture", m_DepthTex = m_Device->CreateTexture2D("PostProcDepthTexture",
Renderer::Backend::ITexture::Usage::SAMPLED | Renderer::Backend::ITexture::Usage::SAMPLED |
@@ -285,24 +336,14 @@ void CPostprocManager::RecreateBuffers()
Renderer::Backend::Sampler::Filter::LINEAR, Renderer::Backend::Sampler::Filter::LINEAR,
Renderer::Backend::Sampler::AddressMode::CLAMP_TO_EDGE)); Renderer::Backend::Sampler::AddressMode::CLAMP_TO_EDGE));
RecreateCaptureFramebuffer();
// Set up the framebuffers with some initial textures. // Set up the framebuffers with some initial textures.
Renderer::Backend::SColorAttachment colorAttachment{}; Renderer::Backend::SColorAttachment colorAttachment{};
colorAttachment.texture = m_ColorTex1.get();
colorAttachment.loadOp = Renderer::Backend::AttachmentLoadOp::DONT_CARE;
colorAttachment.storeOp = Renderer::Backend::AttachmentStoreOp::STORE;
colorAttachment.clearColor = CColor{0.0f, 0.0f, 0.0f, 0.0f};
Renderer::Backend::SDepthStencilAttachment depthStencilAttachment{};
depthStencilAttachment.texture = m_DepthTex.get();
depthStencilAttachment.loadOp = Renderer::Backend::AttachmentLoadOp::CLEAR;
depthStencilAttachment.storeOp = Renderer::Backend::AttachmentStoreOp::STORE;
m_CaptureFramebuffer = m_Device->CreateFramebuffer("PostprocCaptureFramebuffer",
&colorAttachment, &depthStencilAttachment);
colorAttachment.texture = m_ColorTex1.get(); colorAttachment.texture = m_ColorTex1.get();
colorAttachment.loadOp = Renderer::Backend::AttachmentLoadOp::LOAD; colorAttachment.loadOp = Renderer::Backend::AttachmentLoadOp::LOAD;
colorAttachment.storeOp = Renderer::Backend::AttachmentStoreOp::STORE; colorAttachment.storeOp = Renderer::Backend::AttachmentStoreOp::STORE;
colorAttachment.clearColor = CColor{0.0f, 0.0f, 0.0f, 0.0f};
m_PingFramebuffer = m_Device->CreateFramebuffer("PostprocPingFramebuffer", m_PingFramebuffer = m_Device->CreateFramebuffer("PostprocPingFramebuffer",
&colorAttachment, nullptr); &colorAttachment, nullptr);
@@ -310,7 +351,7 @@ void CPostprocManager::RecreateBuffers()
m_PongFramebuffer = m_Device->CreateFramebuffer("PostprocPongFramebuffer", m_PongFramebuffer = m_Device->CreateFramebuffer("PostprocPongFramebuffer",
&colorAttachment, nullptr); &colorAttachment, nullptr);
if (!m_CaptureFramebuffer || !m_PingFramebuffer || !m_PongFramebuffer) if (!m_PingFramebuffer || !m_PongFramebuffer)
{ {
LOGWARNING("Failed to create postproc framebuffers"); LOGWARNING("Failed to create postproc framebuffers");
g_RenderingOptions.SetPostProc(false); g_RenderingOptions.SetPostProc(false);
@@ -323,6 +364,28 @@ void CPostprocManager::RecreateBuffers()
} }
} }
void CPostprocManager::RecreateCaptureFramebuffer()
{
Renderer::Backend::SColorAttachment colorAttachment{};
colorAttachment.texture = m_PBREnabled ? m_PBROutputTexture.get() : m_ColorTex1.get();
colorAttachment.loadOp = Renderer::Backend::AttachmentLoadOp::DONT_CARE;
colorAttachment.storeOp = Renderer::Backend::AttachmentStoreOp::STORE;
colorAttachment.clearColor = CColor{0.0f, 0.0f, 0.0f, 0.0f};
Renderer::Backend::SDepthStencilAttachment depthStencilAttachment{};
depthStencilAttachment.texture = m_DepthTex.get();
depthStencilAttachment.loadOp = Renderer::Backend::AttachmentLoadOp::CLEAR;
depthStencilAttachment.storeOp = Renderer::Backend::AttachmentStoreOp::STORE;
m_CaptureFramebuffer = m_Device->CreateFramebuffer("PostprocCaptureFramebuffer",
&colorAttachment, m_UsingMultisampleBuffer ? nullptr : &depthStencilAttachment);
if (!m_CaptureFramebuffer)
{
LOGWARNING("Failed to create postproc capture framebuffer");
g_RenderingOptions.SetPostProc(false);
}
}
void CPostprocManager::ApplyBlurDownscale2x( void CPostprocManager::ApplyBlurDownscale2x(
Renderer::Backend::IDeviceCommandContext* deviceCommandContext, Renderer::Backend::IDeviceCommandContext* deviceCommandContext,
@@ -698,17 +761,15 @@ void CPostprocManager::ApplyPostproc(
{ {
ENSURE(m_IsInitialized); ENSURE(m_IsInitialized);
// Don't do anything if we are using the default effect and no AA.
const bool hasEffects{m_PostProcEffect != L"default"};
const bool hasAA{m_AATech};
const bool hasSharp{m_SharpTech};
if (!hasEffects && !hasAA && !hasSharp)
return;
PROFILE3_GPU(deviceCommandContext, "Render postproc"); PROFILE3_GPU(deviceCommandContext, "Render postproc");
GPU_SCOPED_LABEL(deviceCommandContext, "Render postproc"); GPU_SCOPED_LABEL(deviceCommandContext, "Render postproc");
if (hasEffects) if (m_PBREnabled)
{
ResolvePBR(deviceCommandContext);
}
if (!m_PBREnabled && m_PostProcEffect != L"default")
{ {
// First render blur textures. Note that this only happens ONLY ONCE, before any effects are applied! // First render blur textures. Note that this only happens ONLY ONCE, before any effects are applied!
// (This may need to change depending on future usage, however that will have a fps hit) // (This may need to change depending on future usage, however that will have a fps hit)
@@ -717,13 +778,13 @@ void CPostprocManager::ApplyPostproc(
ApplyEffect(deviceCommandContext, m_PostProcTech, pass); ApplyEffect(deviceCommandContext, m_PostProcTech, pass);
} }
if (hasAA) if (m_AATech)
{ {
for (int pass = 0; pass < m_AATech->GetNumPasses(); ++pass) for (int pass = 0; pass < m_AATech->GetNumPasses(); ++pass)
ApplyEffect(deviceCommandContext, m_AATech, pass); ApplyEffect(deviceCommandContext, m_AATech, pass);
} }
if (hasSharp && !ShouldUpscale()) if (m_SharpTech && !ShouldUpscale())
{ {
for (int pass = 0; pass < m_SharpTech->GetNumPasses(); ++pass) for (int pass = 0; pass < m_SharpTech->GetNumPasses(); ++pass)
ApplyEffect(deviceCommandContext, m_SharpTech, pass); ApplyEffect(deviceCommandContext, m_SharpTech, pass);
@@ -815,6 +876,8 @@ void CPostprocManager::UpdateAntiAliasingTechnique()
m_UsingMultisampleBuffer = true; m_UsingMultisampleBuffer = true;
CreateMultisampleBuffer(); CreateMultisampleBuffer();
} }
RecreateCaptureFramebuffer();
} }
void CPostprocManager::UpdateSharpeningTechnique() void CPostprocManager::UpdateSharpeningTechnique()
@@ -871,7 +934,7 @@ void CPostprocManager::CreateMultisampleBuffer()
Renderer::Backend::ITexture::Type::TEXTURE_2D_MULTISAMPLE, Renderer::Backend::ITexture::Type::TEXTURE_2D_MULTISAMPLE,
Renderer::Backend::ITexture::Usage::COLOR_ATTACHMENT | Renderer::Backend::ITexture::Usage::COLOR_ATTACHMENT |
Renderer::Backend::ITexture::Usage::TRANSFER_SRC, Renderer::Backend::ITexture::Usage::TRANSFER_SRC,
Renderer::Backend::Format::R8G8B8A8_UNORM, m_Width, m_Height, m_FramebufferColorFormat, m_Width, m_Height,
Renderer::Backend::Sampler::MakeDefaultSampler( Renderer::Backend::Sampler::MakeDefaultSampler(
Renderer::Backend::Sampler::Filter::LINEAR, Renderer::Backend::Sampler::Filter::LINEAR,
Renderer::Backend::Sampler::AddressMode::CLAMP_TO_EDGE), 1, m_MultisampleCount); Renderer::Backend::Sampler::AddressMode::CLAMP_TO_EDGE), 1, m_MultisampleCount);
@@ -935,7 +998,42 @@ void CPostprocManager::ResolveMultisampleFramebuffer(
GPU_SCOPED_LABEL(deviceCommandContext, "Resolve postproc multisample"); GPU_SCOPED_LABEL(deviceCommandContext, "Resolve postproc multisample");
deviceCommandContext->ResolveFramebuffer( deviceCommandContext->ResolveFramebuffer(
m_MultisampleFramebuffer.get(), m_PingFramebuffer.get()); m_MultisampleFramebuffer.get(),
m_PBREnabled ? m_CaptureFramebuffer.get() : m_PingFramebuffer.get());
}
void CPostprocManager::ResolvePBR(
Renderer::Backend::IDeviceCommandContext* deviceCommandContext)
{
ENSURE(m_PBREnabled);
ENSURE(m_ResolvePBRComputeTech);
GPU_SCOPED_LABEL(deviceCommandContext, "Resolve PBR");
Renderer::Backend::IShaderProgram* shaderProgram{m_ResolvePBRComputeTech->GetShader()};
Renderer::Backend::ITexture* source{m_PBROutputTexture.get()};
Renderer::Backend::ITexture* destination{m_ColorTex1.get()};
const std::array<float, 4> screenSize{{
static_cast<float>(m_Width), static_cast<float>(m_Height),
1.0f / static_cast<float>(m_Width), 1.0f / static_cast<float>(m_Height)}};
constexpr uint32_t threadGroupWorkRegionDim{8};
const uint32_t dispatchGroupCountX{DivideRoundUp(m_Width, threadGroupWorkRegionDim)};
const uint32_t dispatchGroupCountY{DivideRoundUp(m_Height, threadGroupWorkRegionDim)};
deviceCommandContext->BeginComputePass();
deviceCommandContext->SetComputePipelineState(
m_ResolvePBRComputeTech->GetComputePipelineState());
deviceCommandContext->SetUniform(shaderProgram->GetBindingSlot(str_screenSize), screenSize);
// Mapping [0.0, 1.0] to [-2.0, 2.0].
deviceCommandContext->SetUniform(shaderProgram->GetBindingSlot(str_exposure),
std::exp2f((g_RenderingOptions.GetPBRBrightness() - 0.5f) * 4.0f));
deviceCommandContext->SetTexture(shaderProgram->GetBindingSlot(str_inTex), source);
deviceCommandContext->SetStorageTexture(shaderProgram->GetBindingSlot(str_outTex), destination);
deviceCommandContext->Dispatch(dispatchGroupCountX, dispatchGroupCountY, 1);
deviceCommandContext->EndComputePass();
} }
void CPostprocManager::RecalculateSize(const uint32_t width, const uint32_t height) void CPostprocManager::RecalculateSize(const uint32_t width, const uint32_t height)
+22 -1
View File
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Wildfire Games. /* Copyright (C) 2026 Wildfire Games.
* This file is part of 0 A.D. * This file is part of 0 A.D.
* *
* 0 A.D. is free software: you can redistribute it and/or modify * 0 A.D. is free software: you can redistribute it and/or modify
@@ -95,9 +95,16 @@ public:
float GetScale() const { return m_Scale; } float GetScale() const { return m_Scale; }
bool IsPBREnabled() const { return m_PBREnabled; }
Renderer::Backend::Format GetFramebufferColorFormat() const { return m_FramebufferColorFormat; }
private: private:
void CreateMultisampleBuffer(); void CreateMultisampleBuffer();
void DestroyMultisampleBuffer(); void DestroyMultisampleBuffer();
void RecreateCaptureFramebuffer();
void InitializePBR();
void RecalculateSize(const uint32_t width, const uint32_t height); void RecalculateSize(const uint32_t width, const uint32_t height);
@@ -127,8 +134,20 @@ private:
Renderer::Backend::ITexture* source, Renderer::Backend::ITexture* source,
Renderer::Backend::ITexture* destination); Renderer::Backend::ITexture* destination);
/**
* Resolve PBR HDR output to SDR one.
*/
void ResolvePBR(
Renderer::Backend::IDeviceCommandContext* deviceCommandContext);
Renderer::Backend::IDevice* m_Device = nullptr; Renderer::Backend::IDevice* m_Device = nullptr;
Renderer::Backend::Format m_FramebufferColorFormat{
Renderer::Backend::Format::R8G8B8A8_UNORM};
bool m_PBREnabled{false};
std::unique_ptr<Renderer::Backend::ITexture> m_PBROutputTexture;
std::unique_ptr<Renderer::Backend::IFramebuffer> m_CaptureFramebuffer; std::unique_ptr<Renderer::Backend::IFramebuffer> m_CaptureFramebuffer;
// Two framebuffers, that we flip between at each shader pass. // Two framebuffers, that we flip between at each shader pass.
@@ -170,6 +189,8 @@ private:
CStrW m_PostProcEffect; CStrW m_PostProcEffect;
CShaderTechniquePtr m_PostProcTech; CShaderTechniquePtr m_PostProcTech;
CShaderTechniquePtr m_ResolvePBRComputeTech;
CStr m_SharpName; CStr m_SharpName;
CShaderTechniquePtr m_SharpTech; CShaderTechniquePtr m_SharpTech;
float m_Sharpness; float m_Sharpness;
+2
View File
@@ -271,6 +271,8 @@ void CRenderingOptions::ReadConfigAndSetupHooks()
if (CRenderer::IsInitialised()) if (CRenderer::IsInitialised())
g_Renderer.GetTextureManager().OnQualityChanged(); g_Renderer.GetTextureManager().OnQualityChanged();
}); });
m_ConfigHooks->Setup("pbr.brightness", m_PBRBrightness);
} }
void CRenderingOptions::ClearHooks() void CRenderingOptions::ClearHooks()
+2
View File
@@ -120,6 +120,8 @@ OPTION_CUSTOM_SETTER(NAME, TYPE); OPTION_GETTER(NAME, TYPE); OPTION_DEF(NAME, TY
OPTION(DisplayFrustum, bool); OPTION(DisplayFrustum, bool);
OPTION(DisplayShadowsFrustum, bool); OPTION(DisplayShadowsFrustum, bool);
OPTION(PBRBrightness, float);
// Cutscene Mode: while active, (most) visual overlays aren't rendered in order to give the scene a more "pure" // Cutscene Mode: while active, (most) visual overlays aren't rendered in order to give the scene a more "pure"
// and real feel, like a movie. // and real feel, like a movie.
// The idea is for it to be inactive during normal gameplay, but enabled while playing cinema paths and // The idea is for it to be inactive during normal gameplay, but enabled while playing cinema paths and
+7 -2
View File
@@ -260,6 +260,11 @@ void WaterManager::RecreateOrLoadTexturesIfNeeded()
Renderer::Backend::ITexture::Usage::DEPTH_STENCIL_ATTACHMENT, Renderer::Backend::ITexture::Usage::DEPTH_STENCIL_ATTACHMENT,
true, false); true, false);
Renderer::Backend::Format framebufferColorFormat{
g_Renderer.GetPostprocManager().IsEnabled()
? g_Renderer.GetPostprocManager().GetFramebufferColorFormat()
: Renderer::Backend::Format::R8G8B8A8_UNORM};
// Create reflection textures. // Create reflection textures.
const bool needsReflectionTextures = const bool needsReflectionTextures =
g_RenderingOptions.GetWaterEffects() && g_RenderingOptions.GetWaterEffects() &&
@@ -269,7 +274,7 @@ void WaterManager::RecreateOrLoadTexturesIfNeeded()
m_ReflectionTexture = m_Device->CreateTexture2D("WaterReflectionTexture", m_ReflectionTexture = m_Device->CreateTexture2D("WaterReflectionTexture",
Renderer::Backend::ITexture::Usage::SAMPLED | Renderer::Backend::ITexture::Usage::SAMPLED |
Renderer::Backend::ITexture::Usage::COLOR_ATTACHMENT, Renderer::Backend::ITexture::Usage::COLOR_ATTACHMENT,
Renderer::Backend::Format::R8G8B8A8_UNORM, m_RefTextureSize, m_RefTextureSize, framebufferColorFormat, m_RefTextureSize, m_RefTextureSize,
Renderer::Backend::Sampler::MakeDefaultSampler( Renderer::Backend::Sampler::MakeDefaultSampler(
Renderer::Backend::Sampler::Filter::LINEAR, Renderer::Backend::Sampler::Filter::LINEAR,
Renderer::Backend::Sampler::AddressMode::MIRRORED_REPEAT)); Renderer::Backend::Sampler::AddressMode::MIRRORED_REPEAT));
@@ -312,7 +317,7 @@ void WaterManager::RecreateOrLoadTexturesIfNeeded()
m_RefractionTexture = m_Device->CreateTexture2D("WaterRefractionTexture", m_RefractionTexture = m_Device->CreateTexture2D("WaterRefractionTexture",
Renderer::Backend::ITexture::Usage::SAMPLED | Renderer::Backend::ITexture::Usage::SAMPLED |
Renderer::Backend::ITexture::Usage::COLOR_ATTACHMENT, Renderer::Backend::ITexture::Usage::COLOR_ATTACHMENT,
Renderer::Backend::Format::R8G8B8A8_UNORM, m_RefTextureSize, m_RefTextureSize, framebufferColorFormat, m_RefTextureSize, m_RefTextureSize,
Renderer::Backend::Sampler::MakeDefaultSampler( Renderer::Backend::Sampler::MakeDefaultSampler(
Renderer::Backend::Sampler::Filter::LINEAR, Renderer::Backend::Sampler::Filter::LINEAR,
Renderer::Backend::Sampler::AddressMode::MIRRORED_REPEAT)); Renderer::Backend::Sampler::AddressMode::MIRRORED_REPEAT));
+1 -1
View File
@@ -968,7 +968,7 @@ bool CDevice::IsTextureFormatSupported(const Format format) const
case Format::R16G16B16A16_SFLOAT: case Format::R16G16B16A16_SFLOAT:
case Format::R32G32B32A32_SFLOAT: case Format::R32G32B32A32_SFLOAT:
supported = m_Capabilities.computeShaders && m_Capabilities.storage && ogl_HaveExtension("GL_ARB_texture_float"); supported = m_Capabilities.computeShaders && m_Capabilities.storage && GLAD_GL_ARB_texture_float;
break; break;
default: default:
+1 -1
View File
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Wildfire Games. /* Copyright (C) 2026 Wildfire Games.
* This file is part of 0 A.D. * This file is part of 0 A.D.
* *
* 0 A.D. is free software: you can redistribute it and/or modify * 0 A.D. is free software: you can redistribute it and/or modify