diff --git a/interface/resources/qml/Stats.qml b/interface/resources/qml/Stats.qml
index 2406fa048d..bff13cea54 100644
--- a/interface/resources/qml/Stats.qml
+++ b/interface/resources/qml/Stats.qml
@@ -263,6 +263,12 @@ Item {
}
StatText {
text: "GPU: " + root.gpuFrameTime.toFixed(1) + " ms"
+ }
+ StatText {
+ text: "GPU (Per pixel): " + root.gpuFrameTimePerPixel.toFixed(5) + " ns/pp"
+ }
+ StatText {
+ text: "GPU frame size: " + root.gpuFrameSize.x + " x " + root.gpuFrameSize.y
}
StatText {
text: "Triangles: " + root.triangles +
diff --git a/interface/src/ui/Stats.cpp b/interface/src/ui/Stats.cpp
index c7ee868855..6bb615948c 100644
--- a/interface/src/ui/Stats.cpp
+++ b/interface/src/ui/Stats.cpp
@@ -333,7 +333,13 @@ void Stats::updateStats(bool force) {
}
auto gpuContext = qApp->getGPUContext();
-
+ auto displayPlugin = qApp->getActiveDisplayPlugin();
+ if (displayPlugin) {
+ QVector2D dims(displayPlugin->getRecommendedRenderSize().x, displayPlugin->getRecommendedRenderSize().y);
+ dims *= displayPlugin->getRenderResolutionScale();
+ STAT_UPDATE(gpuFrameSize, dims);
+ STAT_UPDATE(gpuFrameTimePerPixel, (float)(gpuContext->getFrameTimerGPUAverage()*1000000.0 / double(dims.x()*dims.y())));
+ }
// Update Frame timing (in ms)
STAT_UPDATE(gpuFrameTime, (float)gpuContext->getFrameTimerGPUAverage());
STAT_UPDATE(batchFrameTime, (float)gpuContext->getFrameTimerBatchAverage());
diff --git a/interface/src/ui/Stats.h b/interface/src/ui/Stats.h
index 36e923261d..f4181f9788 100644
--- a/interface/src/ui/Stats.h
+++ b/interface/src/ui/Stats.h
@@ -276,7 +276,9 @@ class Stats : public QQuickItem {
STATS_PROPERTY(int, gpuTextureExternalMemory, 0)
STATS_PROPERTY(QString, gpuTextureMemoryPressureState, QString())
STATS_PROPERTY(int, gpuFreeMemory, 0)
+ STATS_PROPERTY(QVector2D, gpuFrameSize, QVector2D(0,0))
STATS_PROPERTY(float, gpuFrameTime, 0)
+ STATS_PROPERTY(float, gpuFrameTimePerPixel, 0)
STATS_PROPERTY(float, batchFrameTime, 0)
STATS_PROPERTY(float, engineFrameTime, 0)
STATS_PROPERTY(float, avatarSimulationTime, 0)
@@ -962,6 +964,20 @@ signals:
*/
void gpuFrameTimeChanged();
+ /**jsdoc
+ * Triggered when the value of the gpuFrameTime
property changes.
+ * @function Stats.gpuFrameTimeChanged
+ * @returns {Signal}
+ */
+ void gpuFrameSizeChanged();
+
+ /**jsdoc
+ * Triggered when the value of the gpuFrameTime
property changes.
+ * @function Stats.gpuFrameTimeChanged
+ * @returns {Signal}
+ */
+ void gpuFrameTimePerPixelChanged();
+
/**jsdoc
* Triggered when the value of the batchFrameTime
property changes.
* @function Stats.batchFrameTimeChanged
diff --git a/libraries/graphics/src/graphics/Haze.cpp b/libraries/graphics/src/graphics/Haze.cpp
index d5a060b90b..ded48429ba 100644
--- a/libraries/graphics/src/graphics/Haze.cpp
+++ b/libraries/graphics/src/graphics/Haze.cpp
@@ -177,9 +177,9 @@ void Haze::setHazeBaseReference(const float hazeBaseReference) {
void Haze::setHazeBackgroundBlend(const float hazeBackgroundBlend) {
auto& params = _hazeParametersBuffer.get();
-
- if (params.hazeBackgroundBlend != hazeBackgroundBlend) {
- _hazeParametersBuffer.edit().hazeBackgroundBlend = hazeBackgroundBlend;
+ auto newBlend = 1.0f - hazeBackgroundBlend;
+ if (params.hazeBackgroundBlend != newBlend) {
+ _hazeParametersBuffer.edit().hazeBackgroundBlend = newBlend;
}
}
diff --git a/libraries/render-utils/src/DeferredGlobalLight.slh b/libraries/render-utils/src/DeferredGlobalLight.slh
index d92fc0dbfd..03ec18c321 100644
--- a/libraries/render-utils/src/DeferredGlobalLight.slh
+++ b/libraries/render-utils/src/DeferredGlobalLight.slh
@@ -235,15 +235,14 @@ vec3 evalGlobalLightingAlphaBlendedWithHaze(
// Haze
if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {
- vec4 colorV4 = computeHazeColor(
- vec4(color, 1.0), // fragment original color
+ vec4 hazeColor = computeHazeColor(
positionES, // fragment position in eye coordinates
fragPositionWS, // fragment position in world coordinates
invViewMat[3].xyz, // eye position in world coordinates
lightDirection // keylight direction vector in world coordinates
);
- color = colorV4.rgb;
+ color = mix(color.rgb, hazeColor.rgb, hazeColor.a);
}
return color;
@@ -273,15 +272,14 @@ vec3 evalGlobalLightingAlphaBlendedWithHaze(
// Haze
if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {
- vec4 colorV4 = computeHazeColor(
- vec4(color, 1.0), // fragment original color
+ vec4 hazeColor = computeHazeColor(
positionES, // fragment position in eye coordinates
positionWS, // fragment position in world coordinates
invViewMat[3].xyz, // eye position in world coordinates
lightDirection // keylight direction vector
);
- color = colorV4.rgb;
+ color = mix(color.rgb, hazeColor.rgb, hazeColor.a);
}
return color;
diff --git a/libraries/render-utils/src/DrawHaze.cpp b/libraries/render-utils/src/DrawHaze.cpp
index e6337d7099..94bac4e3ac 100644
--- a/libraries/render-utils/src/DrawHaze.cpp
+++ b/libraries/render-utils/src/DrawHaze.cpp
@@ -107,11 +107,11 @@ void MakeHaze::run(const render::RenderContextPointer& renderContext, graphics::
haze = _haze;
}
+// Buffer slots
const int HazeEffect_ParamsSlot = 0;
const int HazeEffect_TransformBufferSlot = 1;
-const int HazeEffect_ColorMapSlot = 2;
-const int HazeEffect_LinearDepthMapSlot = 3;
-const int HazeEffect_LightingMapSlot = 4;
+// Texture slots
+const int HazeEffect_LinearDepthMapSlot = 0;
void DrawHaze::configure(const Config& config) {
}
@@ -122,11 +122,10 @@ void DrawHaze::run(const render::RenderContextPointer& renderContext, const Inpu
return;
}
- const auto inputBuffer = inputs.get1()->getRenderBuffer(0);
+ const auto outputBuffer = inputs.get1();
const auto framebuffer = inputs.get2();
const auto transformBuffer = inputs.get3();
-
- auto outputBuffer = inputs.get4();
+ const auto lightingModel = inputs.get4();
auto depthBuffer = framebuffer->getLinearDepthTexture();
@@ -139,6 +138,10 @@ void DrawHaze::run(const render::RenderContextPointer& renderContext, const Inpu
gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps);
gpu::StatePointer state = gpu::StatePointer(new gpu::State());
+ state->setBlendFunction(true,
+ 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);
+
// Mask out haze on the tablet
PrepareStencil::testMask(*state);
@@ -148,15 +151,15 @@ void DrawHaze::run(const render::RenderContextPointer& renderContext, const Inpu
gpu::Shader::BindingSet slotBindings;
slotBindings.insert(gpu::Shader::Binding(std::string("hazeBuffer"), HazeEffect_ParamsSlot));
slotBindings.insert(gpu::Shader::Binding(std::string("deferredFrameTransformBuffer"), HazeEffect_TransformBufferSlot));
- slotBindings.insert(gpu::Shader::Binding(std::string("colorMap"), HazeEffect_ColorMapSlot));
+ slotBindings.insert(gpu::Shader::Binding(std::string("lightingModelBuffer"), render::ShapePipeline::Slot::LIGHTING_MODEL));
slotBindings.insert(gpu::Shader::Binding(std::string("linearDepthMap"), HazeEffect_LinearDepthMapSlot));
- slotBindings.insert(gpu::Shader::Binding(std::string("keyLightBuffer"), HazeEffect_LightingMapSlot));
+ slotBindings.insert(gpu::Shader::Binding(std::string("keyLightBuffer"), render::ShapePipeline::Slot::KEY_LIGHT));
gpu::Shader::makeProgram(*program, slotBindings);
});
});
}
- auto sourceFramebufferSize = glm::ivec2(inputBuffer->getDimensions());
+ auto outputFramebufferSize = glm::ivec2(outputBuffer->getSize());
gpu::doInBatch("DrawHaze::run", args->_context, [&](gpu::Batch& batch) {
batch.enableStereo(false);
@@ -165,7 +168,7 @@ void DrawHaze::run(const render::RenderContextPointer& renderContext, const Inpu
batch.setViewportTransform(args->_viewport);
batch.setProjectionTransform(glm::mat4());
batch.resetViewTransform();
- batch.setModelTransform(gpu::Framebuffer::evalSubregionTexcoordTransform(sourceFramebufferSize, args->_viewport));
+ batch.setModelTransform(gpu::Framebuffer::evalSubregionTexcoordTransform(outputFramebufferSize, args->_viewport));
batch.setPipeline(_hazePipeline);
@@ -181,17 +184,17 @@ void DrawHaze::run(const render::RenderContextPointer& renderContext, const Inpu
}
batch.setUniformBuffer(HazeEffect_TransformBufferSlot, transformBuffer->getFrameTransformBuffer());
+ batch.setUniformBuffer(render::ShapePipeline::Slot::LIGHTING_MODEL, lightingModel->getParametersBuffer());
auto lightStage = args->_scene->getStage();
if (lightStage) {
graphics::LightPointer keyLight;
keyLight = lightStage->getCurrentKeyLight();
if (keyLight) {
- batch.setUniformBuffer(HazeEffect_LightingMapSlot, keyLight->getLightSchemaBuffer());
+ batch.setUniformBuffer(render::ShapePipeline::Slot::KEY_LIGHT, keyLight->getLightSchemaBuffer());
}
}
- batch.setResourceTexture(HazeEffect_ColorMapSlot, inputBuffer);
batch.setResourceTexture(HazeEffect_LinearDepthMapSlot, depthBuffer);
batch.draw(gpu::TRIANGLE_STRIP, 4);
diff --git a/libraries/render-utils/src/DrawHaze.h b/libraries/render-utils/src/DrawHaze.h
index e7d4e15d77..e30ce26dd4 100644
--- a/libraries/render-utils/src/DrawHaze.h
+++ b/libraries/render-utils/src/DrawHaze.h
@@ -22,6 +22,7 @@
#include
#include "SurfaceGeometryPass.h"
+#include "LightingModel.h"
using LinearDepthFramebufferPointer = std::shared_ptr;
@@ -159,7 +160,7 @@ public:
class DrawHaze {
public:
- using Inputs = render::VaryingSet5;
+ using Inputs = render::VaryingSet5;
using Config = HazeConfig;
using JobModel = render::Job::ModelI;
diff --git a/libraries/render-utils/src/ForwardGlobalLight.slh b/libraries/render-utils/src/ForwardGlobalLight.slh
index eccc44186c..cf5f070c55 100644
--- a/libraries/render-utils/src/ForwardGlobalLight.slh
+++ b/libraries/render-utils/src/ForwardGlobalLight.slh
@@ -228,15 +228,14 @@ vec3 evalGlobalLightingAlphaBlendedWithHaze(
// Haze
// FIXME - temporarily removed until we support it for forward...
/* if ((hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {
- vec4 colorV4 = computeHazeColor(
- vec4(color, 1.0), // fragment original color
+ vec4 hazeColor = computeHazeColor(
positionES, // fragment position in eye coordinates
fragPositionWS, // fragment position in world coordinates
invViewMat[3].xyz, // eye position in world coordinates
lightDirection // keylight direction vector
);
- color = colorV4.rgb;
+ color = mix(color.rgb, hazeColor.rgb, hazeColor.a);
}*/
return color;
diff --git a/libraries/render-utils/src/Haze.slf b/libraries/render-utils/src/Haze.slf
index 6b45a72768..93b66d99ed 100644
--- a/libraries/render-utils/src/Haze.slf
+++ b/libraries/render-utils/src/Haze.slf
@@ -22,7 +22,6 @@
<@include Haze.slh@>
-uniform sampler2D colorMap;
uniform sampler2D linearDepthMap;
vec4 unpackPositionFromZeye(vec2 texcoord) {
@@ -46,7 +45,6 @@ void main(void) {
discard;
}
- vec4 fragColor = texture(colorMap, varTexCoord0);
vec4 fragPositionES = unpackPositionFromZeye(varTexCoord0);
mat4 viewInverse = getViewInverse();
@@ -56,5 +54,8 @@ void main(void) {
Light light = getKeyLight();
vec3 lightDirectionWS = getLightDirection(light);
- outFragColor = computeHazeColor(fragColor, fragPositionES.xyz, fragPositionWS.xyz, eyePositionWS.xyz, lightDirectionWS);
+ outFragColor = computeHazeColor(fragPositionES.xyz, fragPositionWS.xyz, eyePositionWS.xyz, lightDirectionWS);
+ if (outFragColor.a < 1e-4) {
+ discard;
+ }
}
diff --git a/libraries/render-utils/src/Haze.slh b/libraries/render-utils/src/Haze.slh
index ab973ba752..7854ad08ca 100644
--- a/libraries/render-utils/src/Haze.slh
+++ b/libraries/render-utils/src/Haze.slh
@@ -92,22 +92,21 @@ vec3 computeHazeColorKeyLightAttenuation(vec3 color, vec3 lightDirectionWS, vec3
}
// Input:
-// fragColor - fragment original color
// fragPositionES - fragment position in eye coordinates
// fragPositionWS - fragment position in world coordinates
// eyePositionWS - eye position in world coordinates
// Output:
-// fragment colour after haze effect
+// haze colour and alpha contains haze blend factor
//
// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission
//
-vec4 computeHazeColor(vec4 fragColor, vec3 fragPositionES, vec3 fragPositionWS, vec3 eyePositionWS, vec3 lightDirectionWS) {
+vec4 computeHazeColor(vec3 fragPositionES, vec3 fragPositionWS, vec3 eyePositionWS, vec3 lightDirectionWS) {
// Distance to fragment
float distance = length(fragPositionES);
float eyeWorldHeight = eyePositionWS.y;
// Convert haze colour from uniform into a vec4
- vec4 hazeColor = vec4(hazeParams.hazeColor, 1.0);
+ vec4 hazeColor = vec4(hazeParams.hazeColor, 1.0);
// Use the haze colour for the glare colour, if blend is not enabled
vec4 blendedHazeColor;
@@ -149,13 +148,13 @@ vec4 computeHazeColor(vec4 fragColor, vec3 fragPositionES, vec3 fragPositionWS,
vec3 hazeAmount = 1.0 - exp(-hazeIntegral);
// Compute color after haze effect
- potentialFragColor = mix(fragColor, vec4(1.0, 1.0, 1.0, 1.0), vec4(hazeAmount, 1.0));
+ potentialFragColor = vec4(1.0, 1.0, 1.0, hazeAmount);
} else if ((hazeParams.hazeMode & HAZE_MODE_IS_ALTITUDE_BASED) != HAZE_MODE_IS_ALTITUDE_BASED) {
// Haze is based only on range
float hazeAmount = 1.0 - exp(-distance * hazeParams.hazeRangeFactor);
// Compute color after haze effect
- potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);
+ potentialFragColor = vec4(blendedHazeColor.rgb, hazeAmount);
} else {
// Haze is based on both range and altitude
// Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt
@@ -181,16 +180,14 @@ vec4 computeHazeColor(vec4 fragColor, vec3 fragPositionES, vec3 fragPositionWS,
float hazeAmount = 1.0 - exp(-hazeIntegral);
// Compute color after haze effect
- potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);
+ potentialFragColor = vec4(blendedHazeColor.rgb, hazeAmount);
}
// Mix with background at far range
const float BLEND_DISTANCE = 27000.0f;
- vec4 outFragColor;
+ vec4 outFragColor = potentialFragColor;
if (distance > BLEND_DISTANCE) {
- outFragColor = mix(potentialFragColor, fragColor, hazeParams.backgroundBlend);
- } else {
- outFragColor = potentialFragColor;
+ outFragColor.a *= hazeParams.backgroundBlend;
}
return outFragColor;
diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp
index 32bdad280c..a03fb7ce94 100644
--- a/libraries/render-utils/src/RenderDeferredTask.cpp
+++ b/libraries/render-utils/src/RenderDeferredTask.cpp
@@ -174,7 +174,7 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren
// Similar to light stage, background stage has been filled by several potential render items and resolved for the frame in this job
task.addJob("DrawBackgroundDeferred", lightingModel);
- const auto drawHazeInputs = render::Varying(DrawHaze::Inputs(hazeModel, lightingFramebuffer, linearDepthTarget, deferredFrameTransform, lightingFramebuffer));
+ const auto drawHazeInputs = render::Varying(DrawHaze::Inputs(hazeModel, lightingFramebuffer, linearDepthTarget, deferredFrameTransform, lightingModel));
task.addJob("DrawHazeDeferred", drawHazeInputs);
// Render transparent objects forward in LightingBuffer