mirror of
https://github.com/overte-org/overte.git
synced 2025-04-16 01:57:57 +02:00
Separate scale between 3D rendering and HUD
This commit is contained in:
parent
9f4fd47b85
commit
703fc20856
7 changed files with 177 additions and 29 deletions
|
@ -3271,6 +3271,16 @@ void Application::resizeGL() {
|
|||
DependencyManager::get<FramebufferCache>()->setFrameBufferSize(fromGlm(renderSize));
|
||||
}
|
||||
|
||||
auto renderResolutionScale = getRenderResolutionScale();
|
||||
if (displayPlugin->getRenderResolutionScale() != renderResolutionScale) {
|
||||
auto renderConfig = _renderEngine->getConfiguration();
|
||||
assert(renderConfig);
|
||||
auto mainView = renderConfig->getConfig("RenderMainView.RenderDeferredTask");
|
||||
assert(mainView);
|
||||
mainView->setProperty("resolutionScale", renderResolutionScale);
|
||||
displayPlugin->setRenderResolutionScale(renderResolutionScale);
|
||||
}
|
||||
|
||||
// FIXME the aspect ratio for stereo displays is incorrect based on this.
|
||||
float aspectRatio = displayPlugin->getRecommendedAspectRatio();
|
||||
_myCamera.setProjection(glm::perspective(glm::radians(_fieldOfView.get()), aspectRatio,
|
||||
|
|
|
@ -393,34 +393,42 @@ graphics::MeshPointer DeferredLightingEffect::getSpotLightMesh() {
|
|||
return _spotLightMesh;
|
||||
}
|
||||
|
||||
void PreparePrimaryFramebuffer::run(const RenderContextPointer& renderContext, gpu::FramebufferPointer& primaryFramebuffer) {
|
||||
gpu::FramebufferPointer PreparePrimaryFramebuffer::createFramebuffer(const char* name, const glm::uvec2& frameSize) {
|
||||
gpu::FramebufferPointer framebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create(name));
|
||||
auto colorFormat = gpu::Element::COLOR_SRGBA_32;
|
||||
|
||||
auto defaultSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR);
|
||||
auto primaryColorTexture = gpu::Texture::createRenderBuffer(colorFormat, frameSize.x, frameSize.y, gpu::Texture::SINGLE_MIP, defaultSampler);
|
||||
|
||||
framebuffer->setRenderBuffer(0, primaryColorTexture);
|
||||
|
||||
auto depthFormat = gpu::Element(gpu::SCALAR, gpu::UINT32, gpu::DEPTH_STENCIL); // Depth24_Stencil8 texel format
|
||||
auto primaryDepthTexture = gpu::Texture::createRenderBuffer(depthFormat, frameSize.x, frameSize.y, gpu::Texture::SINGLE_MIP, defaultSampler);
|
||||
|
||||
framebuffer->setDepthStencilBuffer(primaryDepthTexture, depthFormat);
|
||||
|
||||
return framebuffer;
|
||||
}
|
||||
|
||||
void PreparePrimaryFramebuffer::configure(const Config& config) {
|
||||
_resolutionScale = config.resolutionScale;
|
||||
}
|
||||
|
||||
void PreparePrimaryFramebuffer::run(const RenderContextPointer& renderContext, Output& primaryFramebuffer) {
|
||||
glm::uvec2 frameSize(renderContext->args->_viewport.z, renderContext->args->_viewport.w);
|
||||
glm::uvec2 scaledFrameSize(glm::vec2(frameSize) * _resolutionScale);
|
||||
|
||||
// Resizing framebuffers instead of re-building them seems to cause issues with threaded
|
||||
// rendering
|
||||
if (_primaryFramebuffer && _primaryFramebuffer->getSize() != frameSize) {
|
||||
_primaryFramebuffer.reset();
|
||||
if (!_primaryFramebuffer || _primaryFramebuffer->getSize() != scaledFrameSize) {
|
||||
_primaryFramebuffer = createFramebuffer("deferredPrimary", scaledFrameSize);
|
||||
}
|
||||
|
||||
if (!_primaryFramebuffer) {
|
||||
_primaryFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("deferredPrimary"));
|
||||
auto colorFormat = gpu::Element::COLOR_SRGBA_32;
|
||||
|
||||
auto defaultSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_POINT);
|
||||
auto primaryColorTexture = gpu::Texture::createRenderBuffer(colorFormat, frameSize.x, frameSize.y, gpu::Texture::SINGLE_MIP, defaultSampler);
|
||||
|
||||
|
||||
_primaryFramebuffer->setRenderBuffer(0, primaryColorTexture);
|
||||
|
||||
|
||||
auto depthFormat = gpu::Element(gpu::SCALAR, gpu::UINT32, gpu::DEPTH_STENCIL); // Depth24_Stencil8 texel format
|
||||
auto primaryDepthTexture = gpu::Texture::createRenderBuffer(depthFormat, frameSize.x, frameSize.y, gpu::Texture::SINGLE_MIP, defaultSampler);
|
||||
|
||||
_primaryFramebuffer->setDepthStencilBuffer(primaryDepthTexture, depthFormat);
|
||||
}
|
||||
|
||||
|
||||
primaryFramebuffer = _primaryFramebuffer;
|
||||
|
||||
// Set viewport for the rest of the scaled passes
|
||||
renderContext->args->_viewport.z = scaledFrameSize.x;
|
||||
renderContext->args->_viewport.w = scaledFrameSize.y;
|
||||
}
|
||||
|
||||
void PrepareDeferred::run(const RenderContextPointer& renderContext, const Inputs& inputs, Outputs& outputs) {
|
||||
|
|
|
@ -93,13 +93,34 @@ private:
|
|||
friend class RenderDeferredCleanup;
|
||||
};
|
||||
|
||||
class PreparePrimaryFramebufferConfig : public render::Job::Config {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(float resolutionScale MEMBER resolutionScale NOTIFY dirty)
|
||||
public:
|
||||
|
||||
float resolutionScale{ 1.0f };
|
||||
|
||||
signals:
|
||||
void dirty();
|
||||
};
|
||||
|
||||
class PreparePrimaryFramebuffer {
|
||||
public:
|
||||
using JobModel = render::Job::ModelO<PreparePrimaryFramebuffer, gpu::FramebufferPointer>;
|
||||
|
||||
void run(const render::RenderContextPointer& renderContext, gpu::FramebufferPointer& primaryFramebuffer);
|
||||
using Output = gpu::FramebufferPointer;
|
||||
using Config = PreparePrimaryFramebufferConfig;
|
||||
using JobModel = render::Job::ModelO<PreparePrimaryFramebuffer, Output, Config>;
|
||||
|
||||
PreparePrimaryFramebuffer(float resolutionScale = 1.0f) : _resolutionScale{resolutionScale} {}
|
||||
void configure(const Config& config);
|
||||
void run(const render::RenderContextPointer& renderContext, Output& primaryFramebuffer);
|
||||
|
||||
gpu::FramebufferPointer _primaryFramebuffer;
|
||||
float _resolutionScale{ 1.0f };
|
||||
|
||||
private:
|
||||
|
||||
static gpu::FramebufferPointer createFramebuffer(const char* name, const glm::uvec2& size);
|
||||
};
|
||||
|
||||
class PrepareDeferred {
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include <render/DrawStatus.h>
|
||||
#include <render/DrawSceneOctree.h>
|
||||
#include <render/BlurTask.h>
|
||||
#include <render/ResampleTask.h>
|
||||
|
||||
#include "RenderHifi.h"
|
||||
#include "RenderCommonTask.h"
|
||||
|
@ -59,8 +60,14 @@ RenderDeferredTask::RenderDeferredTask()
|
|||
{
|
||||
}
|
||||
|
||||
void RenderDeferredTask::configure(const Config& config)
|
||||
{
|
||||
void RenderDeferredTask::configure(const Config& config) {
|
||||
// Propagate resolution scale to sub jobs who need it
|
||||
auto preparePrimaryBufferConfig = config.getConfig<PreparePrimaryFramebuffer>("PreparePrimaryBuffer");
|
||||
auto upsamplePrimaryBufferConfig = config.getConfig<Upsample>("PrimaryBufferUpscale");
|
||||
assert(preparePrimaryBufferConfig);
|
||||
assert(upsamplePrimaryBufferConfig);
|
||||
preparePrimaryBufferConfig->setProperty("resolutionScale", config.resolutionScale);
|
||||
upsamplePrimaryBufferConfig->setProperty("factor", 1.0f / config.resolutionScale);
|
||||
}
|
||||
|
||||
const render::Varying RenderDeferredTask::addSelectItemJobs(JobModel& task, const char* selectionName,
|
||||
|
@ -103,17 +110,17 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren
|
|||
|
||||
|
||||
// GPU jobs: Start preparing the primary, deferred and lighting buffer
|
||||
const auto primaryFramebuffer = task.addJob<PreparePrimaryFramebuffer>("PreparePrimaryBuffer");
|
||||
const auto scaledPrimaryFramebuffer = task.addJob<PreparePrimaryFramebuffer>("PreparePrimaryBuffer");
|
||||
|
||||
const auto opaqueRangeTimer = task.addJob<BeginGPURangeTimer>("BeginOpaqueRangeTimer", "DrawOpaques");
|
||||
|
||||
const auto prepareDeferredInputs = PrepareDeferred::Inputs(primaryFramebuffer, lightingModel).asVarying();
|
||||
const auto prepareDeferredInputs = PrepareDeferred::Inputs(scaledPrimaryFramebuffer, lightingModel).asVarying();
|
||||
const auto prepareDeferredOutputs = task.addJob<PrepareDeferred>("PrepareDeferred", prepareDeferredInputs);
|
||||
const auto deferredFramebuffer = prepareDeferredOutputs.getN<PrepareDeferred::Outputs>(0);
|
||||
const auto lightingFramebuffer = prepareDeferredOutputs.getN<PrepareDeferred::Outputs>(1);
|
||||
|
||||
// draw a stencil mask in hidden regions of the framebuffer.
|
||||
task.addJob<PrepareStencil>("PrepareStencil", primaryFramebuffer);
|
||||
task.addJob<PrepareStencil>("PrepareStencil", scaledPrimaryFramebuffer);
|
||||
|
||||
// Render opaque objects in DeferredBuffer
|
||||
const auto opaqueInputs = DrawStateSortDeferred::Inputs(opaques, lightingModel, jitter).asVarying();
|
||||
|
@ -223,7 +230,7 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren
|
|||
task.addJob<Bloom>("Bloom", bloomInputs);
|
||||
|
||||
// Lighting Buffer ready for tone mapping
|
||||
const auto toneMappingInputs = ToneMappingDeferred::Inputs(lightingFramebuffer, primaryFramebuffer).asVarying();
|
||||
const auto toneMappingInputs = ToneMappingDeferred::Inputs(lightingFramebuffer, scaledPrimaryFramebuffer).asVarying();
|
||||
task.addJob<ToneMappingDeferred>("ToneMapping", toneMappingInputs);
|
||||
|
||||
{ // Debug the bounds of the rendered items, still look at the zbuffer
|
||||
|
@ -284,6 +291,9 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren
|
|||
task.addJob<DebugZoneLighting>("DrawZoneStack", deferredFrameTransform);
|
||||
}
|
||||
|
||||
// Upscale to finale resolution
|
||||
const auto primaryFramebuffer = task.addJob<render::Upsample>("PrimaryBufferUpscale", scaledPrimaryFramebuffer);
|
||||
|
||||
// Composite the HUD and HUD overlays
|
||||
task.addJob<CompositeHUD>("HUD");
|
||||
|
||||
|
|
|
@ -105,11 +105,13 @@ class RenderDeferredTaskConfig : public render::Task::Config {
|
|||
Q_OBJECT
|
||||
Q_PROPERTY(float fadeScale MEMBER fadeScale NOTIFY dirty)
|
||||
Q_PROPERTY(float fadeDuration MEMBER fadeDuration NOTIFY dirty)
|
||||
Q_PROPERTY(float resolutionScale MEMBER resolutionScale NOTIFY dirty)
|
||||
Q_PROPERTY(bool debugFade MEMBER debugFade NOTIFY dirty)
|
||||
Q_PROPERTY(float debugFadePercent MEMBER debugFadePercent NOTIFY dirty)
|
||||
public:
|
||||
float fadeScale{ 0.5f };
|
||||
float fadeDuration{ 3.0f };
|
||||
float resolutionScale{ 1.f };
|
||||
float debugFadePercent{ 0.f };
|
||||
bool debugFade{ false };
|
||||
|
||||
|
|
|
@ -81,3 +81,69 @@ void HalfDownsample::run(const RenderContextPointer& renderContext, const gpu::F
|
|||
batch.draw(gpu::TRIANGLE_STRIP, 4);
|
||||
});
|
||||
}
|
||||
|
||||
gpu::PipelinePointer Upsample::_pipeline;
|
||||
|
||||
void Upsample::configure(const Config& config) {
|
||||
_factor = config.factor;
|
||||
}
|
||||
|
||||
gpu::FramebufferPointer Upsample::getResampledFrameBuffer(const gpu::FramebufferPointer& sourceFramebuffer) {
|
||||
if (_factor == 1.0f) {
|
||||
return sourceFramebuffer;
|
||||
}
|
||||
|
||||
auto resampledFramebufferSize = glm::uvec2(glm::vec2(sourceFramebuffer->getSize()) * _factor);
|
||||
|
||||
if (!_destinationFrameBuffer || resampledFramebufferSize != _destinationFrameBuffer->getSize()) {
|
||||
_destinationFrameBuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("UpsampledOutput"));
|
||||
|
||||
auto sampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR);
|
||||
auto target = gpu::Texture::createRenderBuffer(sourceFramebuffer->getRenderBuffer(0)->getTexelFormat(), resampledFramebufferSize.x, resampledFramebufferSize.y, gpu::Texture::SINGLE_MIP, sampler);
|
||||
_destinationFrameBuffer->setRenderBuffer(0, target);
|
||||
}
|
||||
return _destinationFrameBuffer;
|
||||
}
|
||||
|
||||
void Upsample::run(const RenderContextPointer& renderContext, const gpu::FramebufferPointer& sourceFramebuffer, gpu::FramebufferPointer& resampledFrameBuffer) {
|
||||
assert(renderContext->args);
|
||||
assert(renderContext->args->hasViewFrustum());
|
||||
RenderArgs* args = renderContext->args;
|
||||
|
||||
resampledFrameBuffer = getResampledFrameBuffer(sourceFramebuffer);
|
||||
if (resampledFrameBuffer != sourceFramebuffer) {
|
||||
if (!_pipeline) {
|
||||
auto vs = gpu::StandardShaderLib::getDrawTransformUnitQuadVS();
|
||||
auto ps = gpu::StandardShaderLib::getDrawTextureOpaquePS();
|
||||
gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps);
|
||||
|
||||
gpu::Shader::BindingSet slotBindings;
|
||||
gpu::Shader::makeProgram(*program, slotBindings);
|
||||
|
||||
gpu::StatePointer state = gpu::StatePointer(new gpu::State());
|
||||
state->setDepthTest(gpu::State::DepthTest(false, false));
|
||||
_pipeline = gpu::Pipeline::create(program, state);
|
||||
}
|
||||
|
||||
const auto bufferSize = resampledFrameBuffer->getSize();
|
||||
glm::ivec4 viewport{ 0, 0, bufferSize.x, bufferSize.y };
|
||||
|
||||
gpu::doInBatch("Upsample::run", args->_context, [&](gpu::Batch& batch) {
|
||||
batch.enableStereo(false);
|
||||
|
||||
batch.setFramebuffer(resampledFrameBuffer);
|
||||
|
||||
batch.setViewportTransform(viewport);
|
||||
batch.setProjectionTransform(glm::mat4());
|
||||
batch.resetViewTransform();
|
||||
batch.setPipeline(_pipeline);
|
||||
|
||||
batch.setModelTransform(gpu::Framebuffer::evalSubregionTexcoordTransform(bufferSize, viewport));
|
||||
batch.setResourceTexture(0, sourceFramebuffer->getRenderBuffer(0));
|
||||
batch.draw(gpu::TRIANGLE_STRIP, 4);
|
||||
});
|
||||
|
||||
// Set full final viewport
|
||||
args->_viewport = viewport;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,6 +36,37 @@ namespace render {
|
|||
|
||||
gpu::FramebufferPointer getResampledFrameBuffer(const gpu::FramebufferPointer& sourceFramebuffer);
|
||||
};
|
||||
|
||||
class UpsampleConfig : public render::Job::Config {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(float factor MEMBER factor NOTIFY dirty)
|
||||
public:
|
||||
|
||||
float factor{ 1.0f };
|
||||
|
||||
signals:
|
||||
void dirty();
|
||||
};
|
||||
|
||||
class Upsample {
|
||||
public:
|
||||
using Config = UpsampleConfig;
|
||||
using JobModel = Job::ModelIO<Upsample, gpu::FramebufferPointer, gpu::FramebufferPointer, Config>;
|
||||
|
||||
Upsample(float factor = 2.0f) : _factor{ factor } {}
|
||||
|
||||
void configure(const Config& config);
|
||||
void run(const RenderContextPointer& renderContext, const gpu::FramebufferPointer& sourceFramebuffer, gpu::FramebufferPointer& resampledFrameBuffer);
|
||||
|
||||
protected:
|
||||
|
||||
static gpu::PipelinePointer _pipeline;
|
||||
|
||||
gpu::FramebufferPointer _destinationFrameBuffer;
|
||||
float _factor{ 2.0f };
|
||||
|
||||
gpu::FramebufferPointer getResampledFrameBuffer(const gpu::FramebufferPointer& sourceFramebuffer);
|
||||
};
|
||||
}
|
||||
|
||||
#endif // hifi_render_ResampleTask_h
|
||||
|
|
Loading…
Reference in a new issue