Merge pull request #12861 from Zvork/taapre

Bloom and Temporal Anti-Aliasing improvements
This commit is contained in:
John Conklin II 2018-04-25 11:16:56 -07:00 committed by GitHub
commit 748c8cdc58
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
35 changed files with 341 additions and 213 deletions

View file

@ -330,16 +330,20 @@ void Web3DOverlay::render(RenderArgs* args) {
renderTransform.setScale(1.0f);
batch.setModelTransform(renderTransform);
// Turn off jitter for these entities
batch.pushProjectionJitter();
auto geometryCache = DependencyManager::get<GeometryCache>();
if (color.a < OPAQUE_ALPHA_THRESHOLD) {
geometryCache->bindWebBrowserProgram(batch, true);
} else {
geometryCache->bindWebBrowserProgram(batch);
}
vec2 halfSize = vec2(size.x, size.y) / 2.0f;
geometryCache->renderQuad(batch, halfSize * -1.0f, halfSize, vec2(0), vec2(1), color, _geometryId);
batch.popProjectionJitter(); // Restore jitter
batch.setResourceTexture(0, nullptr); // restore default white color after me
}
Transform Web3DOverlay::evalRenderTransform() {

View file

@ -249,8 +249,11 @@ void WebEntityRenderer::doRender(RenderArgs* args) {
batch.setResourceTexture(0, _texture);
float fadeRatio = _isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) : 1.0f;
// Turn off jitter for these entities
batch.pushProjectionJitter();
DependencyManager::get<GeometryCache>()->bindWebBrowserProgram(batch, fadeRatio < OPAQUE_ALPHA_THRESHOLD);
DependencyManager::get<GeometryCache>()->renderQuad(batch, topLeft, bottomRight, texMin, texMax, glm::vec4(1.0f, 1.0f, 1.0f, fadeRatio), _geometryId);
batch.popProjectionJitter();
}
bool WebEntityRenderer::hasWebSurface() {

View file

@ -44,8 +44,9 @@ GLBackend::CommandCall GLBackend::_commandCalls[Batch::NUM_COMMANDS] =
(&::gpu::gl::GLBackend::do_setModelTransform),
(&::gpu::gl::GLBackend::do_setViewTransform),
(&::gpu::gl::GLBackend::do_setProjectionTransform),
(&::gpu::gl::GLBackend::do_setViewportTransform),
(&::gpu::gl::GLBackend::do_setProjectionTransform),
(&::gpu::gl::GLBackend::do_setProjectionJitter),
(&::gpu::gl::GLBackend::do_setViewportTransform),
(&::gpu::gl::GLBackend::do_setDepthRangeTransform),
(&::gpu::gl::GLBackend::do_setPipeline),
@ -166,7 +167,18 @@ void GLBackend::renderPassTransfer(const Batch& batch) {
case Batch::COMMAND_drawIndexedInstanced:
case Batch::COMMAND_multiDrawIndirect:
case Batch::COMMAND_multiDrawIndexedIndirect:
_transform.preUpdate(_commandIndex, _stereo);
{
Vec2u outputSize{ 1,1 };
if (_output._framebuffer) {
outputSize.x = _output._framebuffer->getWidth();
outputSize.y = _output._framebuffer->getHeight();
} else if (glm::dot(_transform._projectionJitter, _transform._projectionJitter)>0.0f) {
qCWarning(gpugllogging) << "Jittering needs to have a frame buffer to be set";
}
_transform.preUpdate(_commandIndex, _stereo, outputSize);
}
break;
case Batch::COMMAND_disableContextStereo:
@ -179,8 +191,10 @@ void GLBackend::renderPassTransfer(const Batch& batch) {
case Batch::COMMAND_setViewportTransform:
case Batch::COMMAND_setViewTransform:
case Batch::COMMAND_setProjectionTransform: {
CommandCall call = _commandCalls[(*command)];
case Batch::COMMAND_setProjectionTransform:
case Batch::COMMAND_setProjectionJitter:
{
CommandCall call = _commandCalls[(*command)];
(this->*(call))(batch, *offset);
break;
}
@ -254,6 +268,8 @@ void GLBackend::render(const Batch& batch) {
if (!batch.isStereoEnabled()) {
_stereo._enable = false;
}
// Reset jitter
_transform._projectionJitter = Vec2(0.0f, 0.0f);
{
PROFILE_RANGE(render_gpu_gl_detail, "Transfer");

View file

@ -126,6 +126,7 @@ public:
virtual void do_setModelTransform(const Batch& batch, size_t paramOffset) final;
virtual void do_setViewTransform(const Batch& batch, size_t paramOffset) final;
virtual void do_setProjectionTransform(const Batch& batch, size_t paramOffset) final;
virtual void do_setProjectionJitter(const Batch& batch, size_t paramOffset) final;
virtual void do_setViewportTransform(const Batch& batch, size_t paramOffset) final;
virtual void do_setDepthRangeTransform(const Batch& batch, size_t paramOffset) final;
@ -367,6 +368,7 @@ protected:
Mat4 _projection;
Vec4i _viewport { 0, 0, 1, 1 };
Vec2 _depthRange { 0.0f, 1.0f };
Vec2 _projectionJitter{ 0.0f, 0.0f };
bool _invalidView { false };
bool _invalidProj { false };
bool _invalidViewport { false };
@ -379,7 +381,7 @@ protected:
mutable List::const_iterator _camerasItr;
mutable size_t _currentCameraOffset{ INVALID_OFFSET };
void preUpdate(size_t commandIndex, const StereoState& stereo);
void preUpdate(size_t commandIndex, const StereoState& stereo, Vec2u framebufferSize);
void update(size_t commandIndex, const StereoState& stereo) const;
void bindCurrentCamera(int stereoSide) const;
} _transform;

View file

@ -28,6 +28,12 @@ void GLBackend::do_setProjectionTransform(const Batch& batch, size_t paramOffset
_transform._invalidProj = true;
}
void GLBackend::do_setProjectionJitter(const Batch& batch, size_t paramOffset) {
_transform._projectionJitter.x = batch._params[paramOffset]._float;
_transform._projectionJitter.y = batch._params[paramOffset+1]._float;
_transform._invalidProj = true;
}
void GLBackend::do_setViewportTransform(const Batch& batch, size_t paramOffset) {
memcpy(&_transform._viewport, batch.readData(batch._params[paramOffset]._uint), sizeof(Vec4i));
@ -90,7 +96,7 @@ void GLBackend::syncTransformStateCache() {
_transform._enabledDrawcallInfoBuffer = false;
}
void GLBackend::TransformStageState::preUpdate(size_t commandIndex, const StereoState& stereo) {
void GLBackend::TransformStageState::preUpdate(size_t commandIndex, const StereoState& stereo, Vec2u framebufferSize) {
// Check all the dirty flags and update the state accordingly
if (_invalidViewport) {
_camera._viewport = glm::vec4(_viewport);
@ -117,20 +123,21 @@ void GLBackend::TransformStageState::preUpdate(size_t commandIndex, const Stereo
if (_invalidView || _invalidProj || _invalidViewport) {
size_t offset = _cameraUboSize * _cameras.size();
Vec2 finalJitter = _projectionJitter / Vec2(framebufferSize);
_cameraOffsets.push_back(TransformStageState::Pair(commandIndex, offset));
if (stereo.isStereo()) {
#ifdef GPU_STEREO_CAMERA_BUFFER
_cameras.push_back(CameraBufferElement(_camera.getEyeCamera(0, stereo, _view), _camera.getEyeCamera(1, stereo, _view)));
_cameras.push_back(CameraBufferElement(_camera.getEyeCamera(0, stereo, _view, finalJitter), _camera.getEyeCamera(1, stereo, _view, finalJitter)));
#else
_cameras.push_back((_camera.getEyeCamera(0, stereo, _view)));
_cameras.push_back((_camera.getEyeCamera(1, stereo, _view)));
_cameras.push_back((_camera.getEyeCamera(0, stereo, _view, finalJitter)));
_cameras.push_back((_camera.getEyeCamera(1, stereo, _view, finalJitter)));
#endif
} else {
#ifdef GPU_STEREO_CAMERA_BUFFER
_cameras.push_back(CameraBufferElement(_camera.recomputeDerived(_view)));
_cameras.push_back(CameraBufferElement(_camera.getMonoCamera(_view, finalJitter)));
#else
_cameras.push_back((_camera.recomputeDerived(_view)));
_cameras.push_back((_camera.getMonoCamera(_view, finalJitter)));
#endif
}
}

View file

@ -265,6 +265,22 @@ void Batch::setProjectionTransform(const Mat4& proj) {
_params.emplace_back(cacheData(sizeof(Mat4), &proj));
}
void Batch::setProjectionJitter(float jx, float jy) {
_projectionJitter.x = jx;
_projectionJitter.y = jy;
pushProjectionJitter(jx, jy);
}
void Batch::pushProjectionJitter(float jx, float jy) {
ADD_COMMAND(setProjectionJitter);
_params.emplace_back(jx);
_params.emplace_back(jy);
}
void Batch::popProjectionJitter() {
pushProjectionJitter(_projectionJitter.x, _projectionJitter.y);
}
void Batch::setViewportTransform(const Vec4i& viewport) {
ADD_COMMAND(setViewportTransform);

View file

@ -167,6 +167,10 @@ public:
void resetViewTransform() { setViewTransform(Transform(), false); }
void setViewTransform(const Transform& view, bool camera = true);
void setProjectionTransform(const Mat4& proj);
void setProjectionJitter(float jx = 0.0f, float jy = 0.0f);
// Very simple 1 level stack management of jitter.
void pushProjectionJitter(float jx = 0.0f, float jy = 0.0f);
void popProjectionJitter();
// Viewport is xy = low left corner in framebuffer, zw = width height of the viewport, expressed in pixels
void setViewportTransform(const Vec4i& viewport);
void setDepthRangeTransform(float nearDepth, float farDepth);
@ -292,8 +296,9 @@ public:
COMMAND_setModelTransform,
COMMAND_setViewTransform,
COMMAND_setProjectionTransform,
COMMAND_setViewportTransform,
COMMAND_setProjectionTransform,
COMMAND_setProjectionJitter,
COMMAND_setViewportTransform,
COMMAND_setDepthRangeTransform,
COMMAND_setPipeline,
@ -496,6 +501,7 @@ public:
NamedBatchDataMap _namedData;
glm::vec2 _projectionJitter{ 0.0f, 0.0f };
bool _enableStereo{ true };
bool _enableSkybox { false };

View file

@ -41,15 +41,19 @@ vec3 color_LinearToYCoCg(vec3 rgb) {
);
}
vec3 color_YCoCgToLinear(vec3 ycocg) {
vec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {
// R = Y + Co - Cg
// G = Y + Cg
// B = Y - Co - Cg
return clamp(vec3(
return vec3(
ycocg.x + ycocg.y - ycocg.z,
ycocg.x + ycocg.z,
ycocg.x - ycocg.y - ycocg.z
), vec3(0.0), vec3(1.0));
);
}
vec3 color_YCoCgToLinear(vec3 ycocg) {
return clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));
}
<@func declareColorWheel()@>

View file

@ -222,7 +222,7 @@ const Backend::TransformCamera& Backend::TransformCamera::recomputeDerived(const
return *this;
}
Backend::TransformCamera Backend::TransformCamera::getEyeCamera(int eye, const StereoState& _stereo, const Transform& xformView) const {
Backend::TransformCamera Backend::TransformCamera::getEyeCamera(int eye, const StereoState& _stereo, const Transform& xformView, Vec2 normalizedJitter) const {
TransformCamera result = *this;
Transform offsetTransform = xformView;
if (!_stereo._skybox) {
@ -231,6 +231,9 @@ Backend::TransformCamera Backend::TransformCamera::getEyeCamera(int eye, const S
// FIXME: If "skybox" the ipd is set to 0 for now, let s try to propose a better solution for this in the future
}
result._projection = _stereo._eyeProjections[eye];
normalizedJitter.x *= 2.0f;
result._projection[2][0] += normalizedJitter.x;
result._projection[2][1] += normalizedJitter.y;
result.recomputeDerived(offsetTransform);
result._stereoInfo = Vec4(1.0f, (float)eye, 0.0f, 0.0f);
@ -238,6 +241,14 @@ Backend::TransformCamera Backend::TransformCamera::getEyeCamera(int eye, const S
return result;
}
Backend::TransformCamera Backend::TransformCamera::getMonoCamera(const Transform& xformView, Vec2 normalizedJitter) const {
TransformCamera result = *this;
result._projection[2][0] += normalizedJitter.x;
result._projection[2][1] += normalizedJitter.y;
result.recomputeDerived(xformView);
return result;
}
// Counters for Buffer and Texture usage in GPU/Context
ContextMetricSize Backend::freeGPUMemSize;

View file

@ -64,19 +64,16 @@ public:
virtual void recycle() const = 0;
virtual void downloadFramebuffer(const FramebufferPointer& srcFramebuffer, const Vec4i& region, QImage& destImage) = 0;
// UBO class... layout MUST match the layout in Transform.slh
class TransformCamera {
public:
mutable Mat4 _view;
mutable Mat4 _viewInverse;
mutable Mat4 _projectionViewUntranslated;
Mat4 _projection;
mutable Mat4 _projectionInverse;
Vec4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.
mutable Vec4 _stereoInfo;
// Shared header between C++ and GLSL
#include "TransformCamera_shared.slh"
class TransformCamera : public _TransformCamera {
public:
const Backend::TransformCamera& recomputeDerived(const Transform& xformView) const;
TransformCamera getEyeCamera(int eye, const StereoState& stereo, const Transform& xformView) const;
// Jitter should be divided by framebuffer size
TransformCamera getMonoCamera(const Transform& xformView, Vec2 normalizedJitter) const;
// Jitter should be divided by framebuffer size
TransformCamera getEyeCamera(int eye, const StereoState& stereo, const Transform& xformView, Vec2 normalizedJitter) const;
};
@ -136,7 +133,6 @@ protected:
friend class Context;
mutable ContextStats _stats;
StereoState _stereo;
};
class Context {

View file

@ -11,20 +11,14 @@
<@def GPU_TRANSFORM_STATE_SLH@>
<@func declareStandardCameraTransform()@>
struct TransformCamera {
mat4 _view;
mat4 _viewInverse;
mat4 _projectionViewUntranslated;
mat4 _projection;
mat4 _projectionInverse;
vec4 _viewport;
vec4 _stereoInfo;
};
<@include gpu/TransformCamera_shared.slh@>
#define TransformCamera _TransformCamera
layout(std140) uniform transformCameraBuffer {
#ifdef GPU_TRANSFORM_IS_STEREO
#ifdef GPU_TRANSFORM_STEREO_CAMERA
TransformCamera _camera[2];
TransformCamera _camera[2];
#else
TransformCamera _camera;
#endif

View file

@ -0,0 +1,26 @@
// glsl / C++ compatible source as interface for FadeEffect
#ifdef __cplusplus
# define _MAT4 Mat4
# define _VEC4 Vec4
# define _MUTABLE mutable
#else
# define _MAT4 mat4
# define _VEC4 vec4
# define _MUTABLE
#endif
struct _TransformCamera {
_MUTABLE _MAT4 _view;
_MUTABLE _MAT4 _viewInverse;
_MUTABLE _MAT4 _projectionViewUntranslated;
_MAT4 _projection;
_MUTABLE _MAT4 _projectionInverse;
_VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.
_MUTABLE _VEC4 _stereoInfo;
};
// <@if 1@>
// Trigger Scribe include
// <@endif@> <!def that !>
//

View file

@ -187,7 +187,8 @@ const int AntialiasingPass_DepthMapSlot = 3;
const int AntialiasingPass_NextMapSlot = 4;
Antialiasing::Antialiasing() {
Antialiasing::Antialiasing(bool isSharpenEnabled) :
_isSharpenEnabled{ isSharpenEnabled } {
_antialiasingBuffers = std::make_shared<gpu::FramebufferSwapChain>(2U);
}
@ -282,8 +283,11 @@ const gpu::PipelinePointer& Antialiasing::getDebugBlendPipeline() {
}
void Antialiasing::configure(const Config& config) {
_sharpen = config.sharpen;
_params.edit().blend = config.blend;
_sharpen = config.sharpen * 0.25f;
if (!_isSharpenEnabled) {
_sharpen = 0.0f;
}
_params.edit().blend = config.blend * config.blend;
_params.edit().covarianceGamma = config.covarianceGamma;
_params.edit().setConstrainColor(config.constrainColor);
@ -328,11 +332,11 @@ void Antialiasing::run(const render::RenderContextPointer& renderContext, const
if (!_antialiasingBuffers->get(0)) {
// Link the antialiasing FBO to texture
auto format = sourceBuffer->getRenderBuffer(0)->getTexelFormat();
auto defaultSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR, gpu::Sampler::WRAP_CLAMP);
for (int i = 0; i < 2; i++) {
auto& antiAliasingBuffer = _antialiasingBuffers->edit(i);
antiAliasingBuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("antialiasing"));
auto format = gpu::Element::COLOR_SRGBA_32; // DependencyManager::get<FramebufferCache>()->getLightingTexture()->getTexelFormat();
auto defaultSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR);
_antialiasingTextures[i] = gpu::Texture::createRenderBuffer(format, width, height, gpu::Texture::SINGLE_MIP, defaultSampler);
antiAliasingBuffer->setRenderBuffer(0, _antialiasingTextures[i]);
}
@ -380,8 +384,6 @@ void Antialiasing::run(const render::RenderContextPointer& renderContext, const
batch.setResourceTexture(AntialiasingPass_VelocityMapSlot, nullptr);
batch.setResourceTexture(AntialiasingPass_NextMapSlot, nullptr);
});
args->popViewFrustum();
}
@ -495,7 +497,7 @@ void JitterSample::configure(const Config& config) {
_scale = config.scale;
}
void JitterSample::run(const render::RenderContextPointer& renderContext) {
void JitterSample::run(const render::RenderContextPointer& renderContext, Output& jitter) {
auto& current = _sampleSequence.currentIndex;
if (!_freeze) {
if (current >= 0) {
@ -504,39 +506,7 @@ void JitterSample::run(const render::RenderContextPointer& renderContext) {
current = -1;
}
}
auto args = renderContext->args;
auto viewFrustum = args->getViewFrustum();
auto jit = _sampleSequence.offsets[(current < 0 ? SEQUENCE_LENGTH : current)];
auto width = (float)args->_viewport.z;
auto height = (float)args->_viewport.w;
auto jx = 2.0f * jit.x / width;
auto jy = 2.0f * jit.y / height;
if (!args->isStereo()) {
auto projMat = viewFrustum.getProjection();
projMat[2][0] += jx;
projMat[2][1] += jy;
viewFrustum.setProjection(projMat);
viewFrustum.calculate();
args->pushViewFrustum(viewFrustum);
} else {
mat4 projMats[2];
args->_context->getStereoProjections(projMats);
jx *= 2.0f;
for (int i = 0; i < 2; i++) {
auto& projMat = projMats[i];
projMat[2][0] += jx;
projMat[2][1] += jy;
}
args->_context->setStereoProjections(projMats);
}
jitter = _sampleSequence.offsets[(current < 0 ? SEQUENCE_LENGTH : current)];
}

View file

@ -58,14 +58,15 @@ class JitterSample {
public:
enum {
SEQUENCE_LENGTH = 128
SEQUENCE_LENGTH = 64
};
using Config = JitterSampleConfig;
using JobModel = render::Job::Model<JitterSample, Config>;
using Output = glm::vec2;
using JobModel = render::Job::ModelO<JitterSample, Output, Config>;
void configure(const Config& config);
void run(const render::RenderContextPointer& renderContext);
void run(const render::RenderContextPointer& renderContext, Output& jitter);
private:
@ -105,11 +106,11 @@ class AntialiasingConfig : public render::Job::Config {
public:
AntialiasingConfig() : render::Job::Config(true) {}
float blend{ 0.05f };
float sharpen{ 0.15f };
float blend{ 0.25f };
float sharpen{ 0.05f };
bool constrainColor{ true };
float covarianceGamma{ 0.9f };
float covarianceGamma{ 0.65f };
bool feedbackColor{ false };
float debugX{ 0.0f };
@ -131,7 +132,7 @@ signals:
struct TAAParams {
float nope{ 0.0f };
float blend{ 0.05f };
float blend{ 0.15f };
float covarianceGamma{ 1.0f };
float debugShowVelocityThreshold{ 1.0f };
@ -168,7 +169,7 @@ public:
using Config = AntialiasingConfig;
using JobModel = render::Job::ModelI<Antialiasing, Inputs, Config>;
Antialiasing();
Antialiasing(bool isSharpenEnabled = true);
~Antialiasing();
void configure(const Config& config);
void run(const render::RenderContextPointer& renderContext, const Inputs& inputs);
@ -189,6 +190,7 @@ private:
TAAParamsBuffer _params;
float _sharpen{ 0.15f };
int _sharpenLoc{ -1 };
bool _isSharpenEnabled{ true };
};

View file

@ -13,7 +13,7 @@
uniform sampler2D blurMap0;
uniform sampler2D blurMap1;
uniform sampler2D blurMap2;
uniform float intensity;
uniform vec3 intensity;
in vec2 varTexCoord0;
out vec4 outFragColor;
@ -23,5 +23,5 @@ void main(void) {
vec4 blur1 = texture(blurMap1, varTexCoord0);
vec4 blur2 = texture(blurMap2, varTexCoord0);
outFragColor = vec4((blur0.rgb+blur1.rgb+blur2.rgb)*intensity, 1.0f);
outFragColor = vec4(blur0.rgb*intensity.x + blur1.rgb*intensity.y + blur2.rgb*intensity.z, 1.0f);
}

View file

@ -50,7 +50,7 @@ void BloomThreshold::run(const render::RenderContextPointer& renderContext, cons
if (!_outputBuffer || _outputBuffer->getSize() != bufferSize) {
auto colorTexture = gpu::TexturePointer(gpu::Texture::createRenderBuffer(inputBuffer->getTexelFormat(), bufferSize.x, bufferSize.y,
gpu::Texture::SINGLE_MIP, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR_MIP_POINT)));
gpu::Texture::SINGLE_MIP, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR_MIP_POINT, gpu::Sampler::WRAP_CLAMP)));
_outputBuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("BloomThreshold"));
_outputBuffer->setRenderBuffer(0, colorTexture);
@ -93,12 +93,14 @@ void BloomThreshold::run(const render::RenderContextPointer& renderContext, cons
outputs = _outputBuffer;
}
BloomApply::BloomApply() {
BloomApply::BloomApply() : _intensities{ 1.0f, 1.0f, 1.0f } {
}
void BloomApply::configure(const Config& config) {
_intensity = config.intensity;
_intensities.x = config.intensity / 3.0f;
_intensities.y = _intensities.x;
_intensities.z = _intensities.x;
}
void BloomApply::run(const render::RenderContextPointer& renderContext, const Inputs& inputs) {
@ -106,10 +108,10 @@ void BloomApply::run(const render::RenderContextPointer& renderContext, const In
assert(renderContext->args->hasViewFrustum());
RenderArgs* args = renderContext->args;
static auto BLUR0_SLOT = 0;
static auto BLUR1_SLOT = 1;
static auto BLUR2_SLOT = 2;
static auto INTENSITY_SLOT = 3;
static const auto BLUR0_SLOT = 0;
static const auto BLUR1_SLOT = 1;
static const auto BLUR2_SLOT = 2;
static const auto INTENSITY_SLOT = 3;
if (!_pipeline) {
auto vs = gpu::StandardShaderLib::getDrawTransformUnitQuadVS();
@ -149,7 +151,7 @@ void BloomApply::run(const render::RenderContextPointer& renderContext, const In
batch.setResourceTexture(BLUR0_SLOT, blur0FB->getRenderBuffer(0));
batch.setResourceTexture(BLUR1_SLOT, blur1FB->getRenderBuffer(0));
batch.setResourceTexture(BLUR2_SLOT, blur2FB->getRenderBuffer(0));
batch._glUniform1f(INTENSITY_SLOT, _intensity / 3.0f);
batch._glUniform3f(INTENSITY_SLOT, _intensities.x, _intensities.y, _intensities.z);
batch.draw(gpu::TRIANGLE_STRIP, 4);
});
}
@ -306,19 +308,19 @@ float BloomConfig::getIntensity() const {
void BloomConfig::setSize(float value) {
std::string blurName{ "BloomBlurN" };
auto sigma = 0.5f+value*3.5f;
auto task = static_cast<render::Task::TaskConcept*>(_task);
for (auto i = 0; i < BLOOM_BLUR_LEVEL_COUNT; i++) {
blurName.back() = '0' + i;
auto task = static_cast<render::Task::TaskConcept*>(_task);
auto blurJobIt = task->editJob(blurName);
assert(blurJobIt != task->_jobs.end());
auto& gaussianBlur = blurJobIt->edit<render::BlurGaussian>();
auto gaussianBlurParams = gaussianBlur.getParameters();
gaussianBlurParams->setFilterGaussianTaps(5, sigma);
// Gaussian blur increases at each level to have a slower rolloff on the edge
// of the response
sigma *= 1.5f;
gaussianBlurParams->setFilterGaussianTaps(9, sigma);
}
auto blurJobIt = task->getJob("BloomApply");
assert(blurJobIt != task->_jobs.end());
blurJobIt->getConfiguration()->setProperty("sigma", sigma);
}
Bloom::Bloom() {
@ -350,7 +352,7 @@ void Bloom::build(JobModel& task, const render::Varying& inputs, render::Varying
// Mix all blur levels at quarter resolution
const auto applyInput = BloomApply::Inputs(bloomInputBuffer, blurFB0, blurFB1, blurFB2).asVarying();
task.addJob<BloomApply>("BloomApply", applyInput);
// And them blend result in additive manner on top of final color buffer
// And then blend result in additive manner on top of final color buffer
const auto drawInput = BloomDraw::Inputs(frameBuffer, bloomInputBuffer).asVarying();
task.addJob<BloomDraw>("BloomDraw", drawInput);

View file

@ -25,7 +25,7 @@ public:
BloomConfig() : render::Task::Config(false) {}
float size{ 0.8f };
float size{ 0.7f };
void setIntensity(float value);
float getIntensity() const;
@ -41,7 +41,7 @@ class BloomThresholdConfig : public render::Job::Config {
public:
float threshold{ 1.25f };
float threshold{ 0.9f };
signals:
void dirty();
@ -71,10 +71,12 @@ private:
class BloomApplyConfig : public render::Job::Config {
Q_OBJECT
Q_PROPERTY(float intensity MEMBER intensity NOTIFY dirty)
Q_PROPERTY(float sigma MEMBER sigma NOTIFY dirty)
public:
float intensity{ 0.8f };
float intensity{ 0.25f };
float sigma{ 1.0f };
signals:
void dirty();
@ -94,7 +96,7 @@ public:
private:
gpu::PipelinePointer _pipeline;
float _intensity{ 1.0f };
glm::vec3 _intensities;
};
class BloomDraw {

View file

@ -18,7 +18,7 @@ DeferredFrameTransform::DeferredFrameTransform() {
_frameTransformBuffer = gpu::BufferView(std::make_shared<gpu::Buffer>(sizeof(FrameTransform), (const gpu::Byte*) &frameTransform));
}
void DeferredFrameTransform::update(RenderArgs* args) {
void DeferredFrameTransform::update(RenderArgs* args, glm::vec2 jitter) {
// Update the depth info with near and far (same for stereo)
auto nearZ = args->getViewFrustum().getNearClip();
@ -38,12 +38,23 @@ void DeferredFrameTransform::update(RenderArgs* args) {
args->getViewFrustum().evalProjectionMatrix(frameTransformBuffer.projectionMono);
// There may be some sort of mismatch here if the viewport size isn't the same as the frame buffer size as
// jitter is normalized by frame buffer size in TransformCamera. But we should be safe.
jitter.x /= args->_viewport.z;
jitter.y /= args->_viewport.w;
// Running in stereo ?
bool isStereo = args->isStereo();
if (!isStereo) {
frameTransformBuffer.projection[0] = frameTransformBuffer.projectionMono;
frameTransformBuffer.projectionUnjittered[0] = frameTransformBuffer.projectionMono;
frameTransformBuffer.invProjectionUnjittered[0] = glm::inverse(frameTransformBuffer.projectionUnjittered[0]);
frameTransformBuffer.stereoInfo = glm::vec4(0.0f, (float)args->_viewport.z, 0.0f, 0.0f);
frameTransformBuffer.invpixelInfo = glm::vec4(1.0f / args->_viewport.z, 1.0f / args->_viewport.w, 0.0f, 0.0f);
frameTransformBuffer.projection[0] = frameTransformBuffer.projectionUnjittered[0];
frameTransformBuffer.projection[0][2][0] += jitter.x;
frameTransformBuffer.projection[0][2][1] += jitter.y;
frameTransformBuffer.invProjection[0] = glm::inverse(frameTransformBuffer.projection[0]);
} else {
@ -52,22 +63,28 @@ void DeferredFrameTransform::update(RenderArgs* args) {
args->_context->getStereoProjections(projMats);
args->_context->getStereoViews(eyeViews);
jitter.x *= 2.0f;
for (int i = 0; i < 2; i++) {
// Compose the mono Eye space to Stereo clip space Projection Matrix
auto sideViewMat = projMats[i] * eyeViews[i];
frameTransformBuffer.projection[i] = sideViewMat;
frameTransformBuffer.invProjection[i] = glm::inverse(sideViewMat);
}
frameTransformBuffer.projectionUnjittered[i] = sideViewMat;
frameTransformBuffer.invProjectionUnjittered[i] = glm::inverse(sideViewMat);
frameTransformBuffer.projection[i] = frameTransformBuffer.projectionUnjittered[i];
frameTransformBuffer.projection[i][2][0] += jitter.x;
frameTransformBuffer.projection[i][2][1] += jitter.y;
frameTransformBuffer.invProjection[i] = glm::inverse(frameTransformBuffer.projection[i]);
}
frameTransformBuffer.stereoInfo = glm::vec4(1.0f, (float)(args->_viewport.z >> 1), 0.0f, 1.0f);
frameTransformBuffer.invpixelInfo = glm::vec4(1.0f / (float)(args->_viewport.z >> 1), 1.0f / args->_viewport.w, 0.0f, 0.0f);
}
}
void GenerateDeferredFrameTransform::run(const render::RenderContextPointer& renderContext, DeferredFrameTransformPointer& frameTransform) {
void GenerateDeferredFrameTransform::run(const render::RenderContextPointer& renderContext, const Input& jitter, Output& frameTransform) {
if (!frameTransform) {
frameTransform = std::make_shared<DeferredFrameTransform>();
}
frameTransform->update(renderContext->args);
frameTransform->update(renderContext->args, jitter);
}

View file

@ -25,7 +25,7 @@ public:
DeferredFrameTransform();
void update(RenderArgs* args);
void update(RenderArgs* args, glm::vec2 jitter);
UniformBufferView getFrameTransformBuffer() const { return _frameTransformBuffer; }
@ -43,16 +43,20 @@ protected:
glm::vec4 depthInfo;
// Stereo info is { isStereoFrame, halfWidth }
glm::vec4 stereoInfo{ 0.0 };
// Mono proj matrix or Left and Right proj matrix going from Mono Eye space to side clip space
glm::mat4 projection[2];
// Inverse proj matrix or Left and Right proj matrix going from Mono Eye space to side clip space
glm::mat4 invProjection[2];
// THe mono projection for sure
// Mono proj matrix or Left and Right proj matrix going from Mono Eye space to side clip space
glm::mat4 projection[2];
// Inverse proj matrix or Left and Right proj matrix going from Mono Eye space to side clip space
glm::mat4 invProjection[2];
// THe mono projection for sure
glm::mat4 projectionMono;
// Inv View matrix from eye space (mono) to world space
glm::mat4 invView;
// View matrix from world space to eye space (mono)
glm::mat4 view;
// Mono proj matrix or Left and Right proj matrix going from Mono Eye space to side clip space without jittering
glm::mat4 projectionUnjittered[2];
// Inverse proj matrix or Left and Right proj matrix going from Mono Eye space to side clip space without jittering
glm::mat4 invProjectionUnjittered[2];
FrameTransform() {}
};
@ -68,11 +72,14 @@ using DeferredFrameTransformPointer = std::shared_ptr<DeferredFrameTransform>;
class GenerateDeferredFrameTransform {
public:
using JobModel = render::Job::ModelO<GenerateDeferredFrameTransform, DeferredFrameTransformPointer>;
using Input = glm::vec2;
using Output = DeferredFrameTransformPointer;
using JobModel = render::Job::ModelIO<GenerateDeferredFrameTransform, Input, Output>;
GenerateDeferredFrameTransform() {}
void run(const render::RenderContextPointer& renderContext, DeferredFrameTransformPointer& frameTransform);
void run(const render::RenderContextPointer& renderContext, const Input& jitter, Output& frameTransform);
private:
};

View file

@ -35,6 +35,8 @@ struct DeferredFrameTransform {
mat4 _projectionMono;
mat4 _viewInverse;
mat4 _view;
mat4 _projectionUnJittered[2];
mat4 _invProjectionUnJittered[2];
};
uniform deferredFrameTransformBuffer {
@ -62,6 +64,12 @@ mat4 getProjection(int side) {
mat4 getProjectionMono() {
return frameTransform._projectionMono;
}
mat4 getUnjitteredProjection(int side) {
return frameTransform._projectionUnJittered[side];
}
mat4 getUnjitteredInvProjection(int side) {
return frameTransform._invProjectionUnJittered[side];
}
// positive near distance of the projection
float getProjectionNear() {
@ -138,6 +146,14 @@ vec3 evalEyePositionFromZdb(int side, float Zdb, vec2 texcoord) {
return eyePos.xyz / eyePos.w;
}
vec3 evalUnjitteredEyePositionFromZdb(int side, float Zdb, vec2 texcoord) {
// compute the view space position using the depth
vec3 clipPos;
clipPos.xyz = vec3(texcoord.xy, Zdb) * 2.0 - 1.0;
vec4 eyePos = frameTransform._invProjectionUnJittered[side] * vec4(clipPos.xyz, 1.0);
return eyePos.xyz / eyePos.w;
}
vec3 evalEyePositionFromZeye(int side, float Zeye, vec2 texcoord) {
float Zdb = evalZdbFromZeye(Zeye);
return evalEyePositionFromZdb(side, Zdb, texcoord);

View file

@ -2207,7 +2207,7 @@ static void buildWebShader(const gpu::ShaderPointer& vertShader, const gpu::Shad
gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,
gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
PrepareStencil::testMaskDrawShape(*state);
PrepareStencil::testMaskDrawShapeNoAA(*state);
pipelinePointerOut = gpu::Pipeline::create(shaderPointerOut, state);
}

View file

@ -11,7 +11,6 @@
<@if not MODEL_MATERIAL_TEXTURES_SLH@>
<@def MODEL_MATERIAL_TEXTURES_SLH@>
<@func declareMaterialTexMapArrayBuffer()@>
const int MAX_TEXCOORDS = 2;
@ -48,6 +47,8 @@ TexMapArray getTexMapArray() {
<@func declareMaterialTextures(withAlbedo, withRoughness, withNormal, withMetallic, withEmissive, withOcclusion, withScattering)@>
#define TAA_TEXTURE_LOD_BIAS -1.0
<@include gpu/TextureTable.slh@>
#ifdef GPU_TEXTURE_TABLE_BINDLESS
@ -66,6 +67,7 @@ TextureTable(0, matTex);
<@if withAlbedo@>
#define albedoMap 0
vec4 fetchAlbedoMap(vec2 uv) {
// Should take into account TAA_TEXTURE_LOD_BIAS?
return tableTexValue(matTex, albedoMap, uv);
}
<@endif@>
@ -73,6 +75,7 @@ vec4 fetchAlbedoMap(vec2 uv) {
<@if withRoughness@>
#define roughnessMap 4
float fetchRoughnessMap(vec2 uv) {
// Should take into account TAA_TEXTURE_LOD_BIAS?
return tableTexValue(matTex, roughnessMap, uv).r;
}
<@endif@>
@ -80,6 +83,7 @@ float fetchRoughnessMap(vec2 uv) {
<@if withNormal@>
#define normalMap 1
vec3 fetchNormalMap(vec2 uv) {
// Should take into account TAA_TEXTURE_LOD_BIAS?
return tableTexValue(matTex, normalMap, uv).xyz;
}
<@endif@>
@ -87,6 +91,7 @@ vec3 fetchNormalMap(vec2 uv) {
<@if withMetallic@>
#define metallicMap 2
float fetchMetallicMap(vec2 uv) {
// Should take into account TAA_TEXTURE_LOD_BIAS?
return tableTexValue(matTex, metallicMap, uv).r;
}
<@endif@>
@ -94,6 +99,7 @@ float fetchMetallicMap(vec2 uv) {
<@if withEmissive@>
#define emissiveMap 3
vec3 fetchEmissiveMap(vec2 uv) {
// Should take into account TAA_TEXTURE_LOD_BIAS?
return tableTexValue(matTex, emissiveMap, uv).rgb;
}
<@endif@>
@ -119,14 +125,14 @@ float fetchScatteringMap(vec2 uv) {
<@if withAlbedo@>
uniform sampler2D albedoMap;
vec4 fetchAlbedoMap(vec2 uv) {
return texture(albedoMap, uv);
return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);
}
<@endif@>
<@if withRoughness@>
uniform sampler2D roughnessMap;
float fetchRoughnessMap(vec2 uv) {
return (texture(roughnessMap, uv).r);
return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);
}
<@endif@>
@ -134,7 +140,7 @@ float fetchRoughnessMap(vec2 uv) {
uniform sampler2D normalMap;
vec3 fetchNormalMap(vec2 uv) {
// unpack normal, swizzle to get into hifi tangent space with Y axis pointing out
vec2 t = 2.0 * (texture(normalMap, uv).rg - vec2(0.5, 0.5));
vec2 t = 2.0 * (texture(normalMap, uv, TAA_TEXTURE_LOD_BIAS).rg - vec2(0.5, 0.5));
vec2 t2 = t*t;
return vec3(t.x, sqrt(1.0 - t2.x - t2.y), t.y);
}
@ -143,14 +149,14 @@ vec3 fetchNormalMap(vec2 uv) {
<@if withMetallic@>
uniform sampler2D metallicMap;
float fetchMetallicMap(vec2 uv) {
return (texture(metallicMap, uv).r);
return (texture(metallicMap, uv, TAA_TEXTURE_LOD_BIAS).r);
}
<@endif@>
<@if withEmissive@>
uniform sampler2D emissiveMap;
vec3 fetchEmissiveMap(vec2 uv) {
return texture(emissiveMap, uv).rgb;
return texture(emissiveMap, uv, TAA_TEXTURE_LOD_BIAS).rgb;
}
<@endif@>
@ -164,7 +170,7 @@ float fetchOcclusionMap(vec2 uv) {
<@if withScattering@>
uniform sampler2D scatteringMap;
float fetchScatteringMap(vec2 uv) {
float scattering = texture(scatteringMap, uv).r; // boolean scattering for now
float scattering = texture(scatteringMap, uv, TAA_TEXTURE_LOD_BIAS).r; // boolean scattering for now
return max(((scattering - 0.1) / 0.9), 0.0);
return texture(scatteringMap, uv).r; // boolean scattering for now
}
@ -234,8 +240,8 @@ vec3 fetchLightmapMap(vec2 uv) {
vec3 normalizedTangent = normalize(<$interpolatedTangent$>.xyz);
vec3 normalizedBitangent = cross(normalizedNormal, normalizedTangent);
// attenuate the normal map divergence from the mesh normal based on distance
// The attenuation range [20,100] meters from the eye is arbitrary for now
vec3 localNormal = mix(<$fetchedNormal$>, vec3(0.0, 1.0, 0.0), smoothstep(20.0, 100.0, (-<$fragPosES$>).z));
// The attenuation range [30,100] meters from the eye is arbitrary for now
vec3 localNormal = mix(<$fetchedNormal$>, vec3(0.0, 1.0, 0.0), smoothstep(30.0, 100.0, (-<$fragPosES$>).z));
<$normal$> = vec3(normalizedBitangent * localNormal.x + normalizedNormal * localNormal.y + normalizedTangent * localNormal.z);
}
<@endfunc@>

View file

@ -46,6 +46,7 @@ void DrawOverlay3D::run(const RenderContextPointer& renderContext, const Inputs&
const auto& inItems = inputs.get0();
const auto& lightingModel = inputs.get1();
const auto jitter = inputs.get2();
config->setNumDrawn((int)inItems.size());
emit config->numDrawnChanged();
@ -75,7 +76,8 @@ void DrawOverlay3D::run(const RenderContextPointer& renderContext, const Inputs&
args->getViewFrustum().evalViewTransform(viewMat);
batch.setProjectionTransform(projMat);
batch.setViewTransform(viewMat);
batch.setProjectionJitter(jitter.x, jitter.y);
batch.setViewTransform(viewMat);
// Setup lighting model for all items;
batch.setUniformBuffer(render::ShapePipeline::Slot::LIGHTING_MODEL, lightingModel->getParametersBuffer());

View file

@ -60,7 +60,7 @@ protected:
class DrawOverlay3D {
public:
using Inputs = render::VaryingSet2 <render::ItemBounds, LightingModelPointer>;
using Inputs = render::VaryingSet3<render::ItemBounds, LightingModelPointer, glm::vec2>;
using Config = DrawOverlay3DConfig;
using JobModel = render::Job::ModelI<DrawOverlay3D, Inputs, Config>;

View file

@ -95,10 +95,10 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren
fadeEffect->build(task, opaques);
task.addJob<JitterSample>("JitterCam");
const auto jitter = task.addJob<JitterSample>("JitterCam");
// Prepare deferred, generate the shared Deferred Frame Transform
const auto deferredFrameTransform = task.addJob<GenerateDeferredFrameTransform>("DeferredFrameTransform");
const auto deferredFrameTransform = task.addJob<GenerateDeferredFrameTransform>("DeferredFrameTransform", jitter);
const auto lightingModel = task.addJob<MakeLightingModel>("LightingModel");
@ -116,12 +116,11 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren
task.addJob<PrepareStencil>("PrepareStencil", primaryFramebuffer);
// Render opaque objects in DeferredBuffer
const auto opaqueInputs = DrawStateSortDeferred::Inputs(opaques, lightingModel).asVarying();
const auto opaqueInputs = DrawStateSortDeferred::Inputs(opaques, lightingModel, jitter).asVarying();
task.addJob<DrawStateSortDeferred>("DrawOpaqueDeferred", opaqueInputs, shapePlumber);
task.addJob<EndGPURangeTimer>("OpaqueRangeTimer", opaqueRangeTimer);
// Opaque all rendered
// Linear Depth Pass
@ -188,8 +187,37 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren
task.addJob<DebugLightClusters>("DebugLightClusters", debugLightClustersInputs);
}
const auto outlineRangeTimer = task.addJob<BeginGPURangeTimer>("BeginHighlightRangeTimer", "Highlight");
// Select items that need to be outlined
const auto selectionBaseName = "contextOverlayHighlightList";
const auto selectedItems = addSelectItemJobs(task, selectionBaseName, metas, opaques, transparents);
const auto outlineInputs = DrawHighlightTask::Inputs(items.get0(), deferredFramebuffer, lightingFramebuffer, deferredFrameTransform).asVarying();
task.addJob<DrawHighlightTask>("DrawHighlight", outlineInputs);
task.addJob<EndGPURangeTimer>("HighlightRangeTimer", outlineRangeTimer);
const auto overlaysInFrontRangeTimer = task.addJob<BeginGPURangeTimer>("BeginOverlaysInFrontRangeTimer", "BeginOverlaysInFrontRangeTimer");
// Layered Overlays
const auto filteredOverlaysOpaque = task.addJob<FilterLayeredItems>("FilterOverlaysLayeredOpaque", overlayOpaques, Item::LAYER_3D_FRONT);
const auto filteredOverlaysTransparent = task.addJob<FilterLayeredItems>("FilterOverlaysLayeredTransparent", overlayTransparents, Item::LAYER_3D_FRONT);
const auto overlaysInFrontOpaque = filteredOverlaysOpaque.getN<FilterLayeredItems::Outputs>(0);
const auto overlaysInFrontTransparent = filteredOverlaysTransparent.getN<FilterLayeredItems::Outputs>(0);
const auto overlayInFrontOpaquesInputs = DrawOverlay3D::Inputs(overlaysInFrontOpaque, lightingModel, jitter).asVarying();
const auto overlayInFrontTransparentsInputs = DrawOverlay3D::Inputs(overlaysInFrontTransparent, lightingModel, jitter).asVarying();
task.addJob<DrawOverlay3D>("DrawOverlayInFrontOpaque", overlayInFrontOpaquesInputs, true);
task.addJob<DrawOverlay3D>("DrawOverlayInFrontTransparent", overlayInFrontTransparentsInputs, false);
task.addJob<EndGPURangeTimer>("OverlaysInFrontRangeTimer", overlaysInFrontRangeTimer);
const auto toneAndPostRangeTimer = task.addJob<BeginGPURangeTimer>("BeginToneAndPostRangeTimer", "PostToneOverlaysAntialiasing");
// AA job before bloom to limit flickering
const auto antialiasingInputs = Antialiasing::Inputs(deferredFrameTransform, lightingFramebuffer, linearDepthTarget, velocityBuffer).asVarying();
task.addJob<Antialiasing>("Antialiasing", antialiasingInputs);
// Add bloom
const auto bloomInputs = Bloom::Inputs(deferredFrameTransform, lightingFramebuffer).asVarying();
task.addJob<Bloom>("Bloom", bloomInputs);
@ -198,16 +226,6 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren
const auto toneMappingInputs = ToneMappingDeferred::Inputs(lightingFramebuffer, primaryFramebuffer).asVarying();
task.addJob<ToneMappingDeferred>("ToneMapping", toneMappingInputs);
const auto outlineRangeTimer = task.addJob<BeginGPURangeTimer>("BeginHighlightRangeTimer", "Highlight");
// Select items that need to be outlined
const auto selectionBaseName = "contextOverlayHighlightList";
const auto selectedItems = addSelectItemJobs(task, selectionBaseName, metas, opaques, transparents);
const auto outlineInputs = DrawHighlightTask::Inputs(items.get0(), deferredFramebuffer, primaryFramebuffer, deferredFrameTransform).asVarying();
task.addJob<DrawHighlightTask>("DrawHighlight", outlineInputs);
task.addJob<EndGPURangeTimer>("HighlightRangeTimer", outlineRangeTimer);
{ // Debug the bounds of the rendered items, still look at the zbuffer
task.addJob<DrawBounds>("DrawMetaBounds", metas);
task.addJob<DrawBounds>("DrawOpaqueBounds", opaques);
@ -230,26 +248,11 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren
task.addJob<DrawBounds>("DrawSelectionBounds", selectedItems);
}
// Layered Overlays
const auto filteredOverlaysOpaque = task.addJob<FilterLayeredItems>("FilterOverlaysLayeredOpaque", overlayOpaques, Item::LAYER_3D_FRONT);
const auto filteredOverlaysTransparent = task.addJob<FilterLayeredItems>("FilterOverlaysLayeredTransparent", overlayTransparents, Item::LAYER_3D_FRONT);
const auto overlaysInFrontOpaque = filteredOverlaysOpaque.getN<FilterLayeredItems::Outputs>(0);
const auto overlaysInFrontTransparent = filteredOverlaysTransparent.getN<FilterLayeredItems::Outputs>(0);
const auto overlayInFrontOpaquesInputs = DrawOverlay3D::Inputs(overlaysInFrontOpaque, lightingModel).asVarying();
const auto overlayInFrontTransparentsInputs = DrawOverlay3D::Inputs(overlaysInFrontTransparent, lightingModel).asVarying();
task.addJob<DrawOverlay3D>("DrawOverlayInFrontOpaque", overlayInFrontOpaquesInputs, true);
task.addJob<DrawOverlay3D>("DrawOverlayInFrontTransparent", overlayInFrontTransparentsInputs, false);
{ // Debug the bounds of the rendered Overlay items that are marked drawInFront, still look at the zbuffer
task.addJob<DrawBounds>("DrawOverlayInFrontOpaqueBounds", overlaysInFrontOpaque);
task.addJob<DrawBounds>("DrawOverlayInFrontTransparentBounds", overlaysInFrontTransparent);
}
// AA job
const auto antialiasingInputs = Antialiasing::Inputs(deferredFrameTransform, primaryFramebuffer, linearDepthTarget, velocityBuffer).asVarying();
task.addJob<Antialiasing>("Antialiasing", antialiasingInputs);
// Debugging stages
{
// Debugging Deferred buffer job
@ -285,9 +288,10 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren
const auto overlaysHUDOpaque = filteredOverlaysOpaque.getN<FilterLayeredItems::Outputs>(1);
const auto overlaysHUDTransparent = filteredOverlaysTransparent.getN<FilterLayeredItems::Outputs>(1);
const auto nullJitter = Varying(glm::vec2(0.0f, 0.0f));
const auto overlayHUDOpaquesInputs = DrawOverlay3D::Inputs(overlaysHUDOpaque, lightingModel).asVarying();
const auto overlayHUDTransparentsInputs = DrawOverlay3D::Inputs(overlaysHUDTransparent, lightingModel).asVarying();
const auto overlayHUDOpaquesInputs = DrawOverlay3D::Inputs(overlaysHUDOpaque, lightingModel, nullJitter).asVarying();
const auto overlayHUDTransparentsInputs = DrawOverlay3D::Inputs(overlaysHUDTransparent, lightingModel, nullJitter).asVarying();
task.addJob<DrawOverlay3D>("DrawOverlayHUDOpaque", overlayHUDOpaquesInputs, true);
task.addJob<DrawOverlay3D>("DrawOverlayHUDTransparent", overlayHUDTransparentsInputs, false);
@ -379,6 +383,7 @@ void DrawStateSortDeferred::run(const RenderContextPointer& renderContext, const
const auto& inItems = inputs.get0();
const auto& lightingModel = inputs.get1();
const auto jitter = inputs.get2();
RenderArgs* args = renderContext->args;
@ -395,6 +400,7 @@ void DrawStateSortDeferred::run(const RenderContextPointer& renderContext, const
args->getViewFrustum().evalViewTransform(viewMat);
batch.setProjectionTransform(projMat);
batch.setProjectionJitter(jitter.x, jitter.y);
batch.setViewTransform(viewMat);
// Setup lighting model for all items;

View file

@ -81,7 +81,7 @@ protected:
class DrawStateSortDeferred {
public:
using Inputs = render::VaryingSet2<render::ItemBounds, LightingModelPointer>;
using Inputs = render::VaryingSet3<render::ItemBounds, LightingModelPointer, glm::vec2>;
using Config = DrawStateSortConfig;
using JobModel = render::Job::ModelI<DrawStateSortDeferred, Inputs, Config>;

View file

@ -35,6 +35,9 @@ void main(void) {
pixels[7] = texelFetch(colorTexture, ivec2(gl_FragCoord.xy)+ivec2(0,1), 0);
pixels[8] = texelFetch(colorTexture, ivec2(gl_FragCoord.xy)+ivec2(1,1), 0);
sharpenedPixel = pixels[4]*7.8 - (pixels[1]+pixels[3]+pixels[5]+pixels[7]) - (pixels[0]+pixels[2]+pixels[6]+pixels[8])*0.7;
outFragColor = mix(pixels[4], sharpenedPixel, sharpenIntensity);
sharpenedPixel = pixels[4]*6.8 - (pixels[1]+pixels[3]+pixels[5]+pixels[7]) - (pixels[0]+pixels[2]+pixels[6]+pixels[8])*0.7;
vec4 minColor = max(vec4(0), pixels[4]-vec4(0.5));
vec4 maxColor = pixels[4]+vec4(0.5);
outFragColor = clamp(pixels[4] + sharpenedPixel * sharpenIntensity, minColor, maxColor);
}

View file

@ -20,14 +20,15 @@ uniform vec4 Color;
in vec3 _normalWS;
in vec2 _texCoord0;
const float gamma = 2.2;
const float smoothing = 32.0;
#define TAA_TEXTURE_LOD_BIAS -3.0
const float interiorCutoff = 0.8;
const float outlineExpansion = 0.2;
const float taaBias = pow(2.0, TAA_TEXTURE_LOD_BIAS);
void main() {
float evalSDF(vec2 texCoord) {
// retrieve signed distance
float sdf = texture(Font, _texCoord0).g;
float sdf = textureLod(Font, texCoord, TAA_TEXTURE_LOD_BIAS).g;
if (Outline) {
if (sdf > interiorCutoff) {
sdf = 1.0 - sdf;
@ -35,12 +36,22 @@ void main() {
sdf += outlineExpansion;
}
}
// perform adaptive anti-aliasing of the edges
// The larger we're rendering, the less anti-aliasing we need
float s = smoothing * length(fwidth(_texCoord0));
float w = clamp(s, 0.0, 0.5);
float a = smoothstep(0.5 - w, 0.5 + w, sdf);
// Rely on TAA for anti-aliasing
return step(0.5, sdf);
}
void main() {
vec2 dxTexCoord = dFdx(_texCoord0) * 0.5 * taaBias;
vec2 dyTexCoord = dFdy(_texCoord0) * 0.5 * taaBias;
// Perform 4x supersampling for anisotropic filtering
float a;
a = evalSDF(_texCoord0);
a += evalSDF(_texCoord0+dxTexCoord);
a += evalSDF(_texCoord0+dyTexCoord);
a += evalSDF(_texCoord0+dxTexCoord+dyTexCoord);
a *= 0.25;
// discard if invisible
if (a < 0.01) {
discard;

View file

@ -76,47 +76,39 @@ vec2 taa_getRegionFXAA() {
#define USE_YCOCG 1
vec4 taa_fetchColor(sampler2D map, vec2 uv) {
vec4 c = texture(map, uv);
// Apply rapid pseudo tonemapping as TAA is applied to a tonemapped image, using luminance as weight, as proposed in
// https://de45xmedrsdbp.cloudfront.net/Resources/files/TemporalAA_small-59732822.pdf
float lum = dot(vec3(0.3,0.5,0.2),c.rgb);
c.rgb = c.rgb / (1.0+lum);
#if USE_YCOCG
vec4 c = texture(map, uv);
return vec4(color_LinearToYCoCg(c.rgb), c.a);
return vec4(color_LinearToYCoCg(c.rgb), c.a);
#else
return texture(map, uv);
return c;
#endif
}
vec3 taa_resolveColor(vec3 color) {
#if USE_YCOCG
return color_YCoCgToLinear(color);
#else
return color;
color = max(vec3(0), color_YCoCgToUnclampedLinear(color));
#endif
// Apply rapid inverse tonemapping, using luminance as weight, as proposed in
// https://de45xmedrsdbp.cloudfront.net/Resources/files/TemporalAA_small-59732822.pdf
float lum = dot(vec3(0.3,0.5,0.2),color.rgb);
color = color / (1.0-lum);
return color;
}
vec4 taa_fetchSourceMap(vec2 uv) {
#if USE_YCOCG
vec4 c = texture(sourceMap, uv);
return vec4(color_LinearToYCoCg(c.rgb), c.a);
#else
return texture(sourceMap, uv);
#endif
return taa_fetchColor(sourceMap, uv);
}
vec4 taa_fetchHistoryMap(vec2 uv) {
#if USE_YCOCG
vec4 c = texture(historyMap, uv);
return vec4(color_LinearToYCoCg(c.rgb), c.a);
#else
return texture(historyMap, uv);
#endif
return taa_fetchColor(historyMap, uv);
}
vec4 taa_fetchNextMap(vec2 uv) {
#if USE_YCOCG
vec4 c = texture(nextMap, uv);
return vec4(color_LinearToYCoCg(c.rgb), c.a);
#else
return texture(nextMap, uv);
#endif
return taa_fetchColor(nextMap, uv);
}
vec2 taa_fetchVelocityMap(vec2 uv) {

View file

@ -28,11 +28,11 @@ void main(void) {
float Zdb = texelFetch(depthMap, ivec2(gl_FragCoord.xy), 0).x;
// The position of the pixel fragment in Eye space then in world space
vec3 eyePos = evalEyePositionFromZdb(stereoSide.x, Zdb, texcoordPos);
vec3 eyePos = evalUnjitteredEyePositionFromZdb(stereoSide.x, Zdb, texcoordPos);
vec3 worldPos = (getViewInverse() * vec4(eyePos, 1.0)).xyz;
vec3 prevEyePos = (getPreviousView() * vec4(worldPos, 1.0)).xyz;
vec4 prevClipPos = (frameTransform._projection[stereoSide.x] * vec4(prevEyePos, 1.0));
vec4 prevClipPos = (getUnjitteredProjection(stereoSide.x) * vec4(prevEyePos, 1.0));
vec2 prevUV = 0.5 * (prevClipPos.xy / prevClipPos.w) + vec2(0.5);
//vec2 imageSize = getWidthHeight(0);

View file

@ -163,7 +163,7 @@ bool BlurInOutResource::updateResources(const gpu::FramebufferPointer& sourceFra
//if (sourceFramebuffer->hasDepthStencil()) {
// _blurredFramebuffer->setDepthStencilBuffer(sourceFramebuffer->getDepthStencilBuffer(), sourceFramebuffer->getDepthStencilBufferFormat());
//}
auto blurringSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR_MIP_POINT);
auto blurringSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR_MIP_POINT, gpu::Sampler::WRAP_CLAMP);
auto blurringTarget = gpu::Texture::createRenderBuffer(sourceFramebuffer->getRenderBuffer(0)->getTexelFormat(), blurBufferSize.x, blurBufferSize.y, gpu::Texture::SINGLE_MIP, blurringSampler);
_blurredFramebuffer->setRenderBuffer(0, blurringTarget);
}
@ -186,7 +186,7 @@ bool BlurInOutResource::updateResources(const gpu::FramebufferPointer& sourceFra
/* if (sourceFramebuffer->hasDepthStencil()) {
_outputFramebuffer->setDepthStencilBuffer(sourceFramebuffer->getDepthStencilBuffer(), sourceFramebuffer->getDepthStencilBufferFormat());
}*/
auto blurringSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR_MIP_POINT);
auto blurringSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR_MIP_POINT, gpu::Sampler::WRAP_CLAMP);
auto blurringTarget = gpu::Texture::createRenderBuffer(sourceFramebuffer->getRenderBuffer(0)->getTexelFormat(), blurBufferSize.x, blurBufferSize.y, gpu::Texture::SINGLE_MIP, blurringSampler);
_outputFramebuffer->setRenderBuffer(0, blurringTarget);
}

View file

@ -98,6 +98,7 @@ Rectangle {
property: "covarianceGamma"
max: 1.5
min: 0.5
height: 38
}
Separator {}
HifiControls.CheckBox {
@ -114,6 +115,7 @@ Rectangle {
property: "blend"
max: 1.0
min: 0.0
height: 38
}
ConfigSlider {
@ -162,6 +164,7 @@ Rectangle {
property: "debugShowVelocityThreshold"
max: 50
min: 0.0
height: 38
}
ConfigSlider {
label: qsTr("Debug Orb Zoom")
@ -170,6 +173,7 @@ Rectangle {
property: "debugOrbZoom"
max: 32.0
min: 1.0
height: 38
}
}
}

View file

@ -93,9 +93,10 @@ Item {
integral: false
config: root.config
property: "intensity"
max: 5.0
max: 1.0
min: 0.0
width: 280
height:38
}
ConfigSlider {
label: "Size"
@ -105,6 +106,7 @@ Item {
max: 1.0
min: 0.0
width: 280
height:38
}
ConfigSlider {
label: "Threshold"
@ -114,6 +116,7 @@ Item {
max: 2.0
min: 0.0
width: 280
height:38
}
}
}

View file

@ -15,6 +15,6 @@ var window = new OverlayWindow({
title: 'Bloom',
source: qml,
width: 285,
height: 170,
height: 210,
});
window.closed.connect(function() { Script.stop(); });

View file

@ -98,7 +98,7 @@ void TestWindow::beginFrame() {
_preparePrimaryFramebuffer.run(_renderContext, primaryFramebuffer);
DeferredFrameTransformPointer frameTransform;
_generateDeferredFrameTransform.run(_renderContext, frameTransform);
_generateDeferredFrameTransform.run(_renderContext, glm::vec2(0.0f, 0.0f), frameTransform);
LightingModelPointer lightingModel;
_generateLightingModel.run(_renderContext, lightingModel);