From 5f395654f09eee78afc002328ebe438a3dfe8082 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Mon, 8 Feb 2016 12:29:56 -0800 Subject: [PATCH 1/6] Integrate JobConfig with JSON/qml --- libraries/render/src/render/Task.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libraries/render/src/render/Task.h b/libraries/render/src/render/Task.h index d090938b64..75bc9d8643 100644 --- a/libraries/render/src/render/Task.h +++ b/libraries/render/src/render/Task.h @@ -74,7 +74,7 @@ public: Q_INVOKABLE QString toJSON() { return QJsonDocument(toJsonValue(*this).toObject()).toJson(QJsonDocument::Compact); } public slots: - void load(const QJsonValue& json) { qObjectFromJsonValue(json, *this); } + Q_INVOKABLE void fromJSON(const QJsonValue& json) { qObjectFromJsonValue(json, *this); } }; class TaskConfig : public JobConfig { @@ -85,6 +85,9 @@ public: void init(Task* task) { _task = task; } + // getter for qml integration, prefer the templated getter + Q_INVOKABLE QObject* getConfig(const QString& name) { return QObject::findChild(name); } + // getter for cpp (strictly typed), prefer this getter template typename T::Config* getConfig(std::string job = "") const { QString name = job.empty() ? QString() : QString(job.c_str()); // an empty string is not a null string return findChild(name); From 991d6328ef9b4b371dd6526fdb563f29d89712ab Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Mon, 8 Feb 2016 13:02:35 -0800 Subject: [PATCH 2/6] Fix JSON integration for JobConfig --- libraries/render/src/render/Task.h | 4 +++- libraries/shared/src/shared/JSONHelpers.cpp | 7 +++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/libraries/render/src/render/Task.h b/libraries/render/src/render/Task.h index 75bc9d8643..a47f8e39fe 100644 --- a/libraries/render/src/render/Task.h +++ b/libraries/render/src/render/Task.h @@ -71,10 +71,12 @@ public: bool alwaysEnabled{ true }; bool enabled{ true }; + // This must be named toJSON to integrate with the global scripting JSON object Q_INVOKABLE QString toJSON() { return QJsonDocument(toJsonValue(*this).toObject()).toJson(QJsonDocument::Compact); } + Q_INVOKABLE void load(const QVariantMap& map) { qObjectFromJsonValue(QJsonObject::fromVariantMap(map), *this); } public slots: - Q_INVOKABLE void fromJSON(const QJsonValue& json) { qObjectFromJsonValue(json, *this); } + void load(const QJsonObject& val) { qObjectFromJsonValue(val, *this); } }; class TaskConfig : public JobConfig { diff --git a/libraries/shared/src/shared/JSONHelpers.cpp b/libraries/shared/src/shared/JSONHelpers.cpp index 3aab117370..e717050055 100644 --- a/libraries/shared/src/shared/JSONHelpers.cpp +++ b/libraries/shared/src/shared/JSONHelpers.cpp @@ -111,10 +111,9 @@ void qObjectFromJsonValue(const QJsonValue& j, QObject& o) { for (auto it = object.begin(); it != object.end(); it++) { std::string key = it.key().toStdString(); if (it.value().isObject()) { - QVariant child = o.property(key.c_str()); - if (child.isValid()) { - QObject* object = child.value(); - qObjectFromJsonValue(it.value(), *object); + QObject* child = o.findChild(key.c_str(), Qt::FindChildOption::FindDirectChildrenOnly); + if (child) { + qObjectFromJsonValue(it.value(), *child); } } else { o.setProperty(key.c_str(), it.value()); From dbc59ccc2b86e158855badccc00cad4ec04b2636 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Mon, 8 Feb 2016 12:29:06 -0800 Subject: [PATCH 3/6] Revamp render engine debug JS script --- examples/utilities/tools/render/AO.qml | 101 ++++++++ examples/utilities/tools/render/Buffer.qml | 99 ++++++++ .../utilities/tools/render/ConfigSlider.qml | 58 +++++ .../utilities/tools/render/ItemsSlider.qml | 59 +++++ examples/utilities/tools/render/Tone.qml | 49 ++++ examples/utilities/tools/render/debug.js | 38 +++ examples/utilities/tools/render/main.qml | 64 ++++++ examples/utilities/tools/renderEngineDebug.js | 216 ------------------ 8 files changed, 468 insertions(+), 216 deletions(-) create mode 100644 examples/utilities/tools/render/AO.qml create mode 100644 examples/utilities/tools/render/Buffer.qml create mode 100644 examples/utilities/tools/render/ConfigSlider.qml create mode 100644 examples/utilities/tools/render/ItemsSlider.qml create mode 100644 examples/utilities/tools/render/Tone.qml create mode 100644 examples/utilities/tools/render/debug.js create mode 100644 examples/utilities/tools/render/main.qml delete mode 100755 examples/utilities/tools/renderEngineDebug.js diff --git a/examples/utilities/tools/render/AO.qml b/examples/utilities/tools/render/AO.qml new file mode 100644 index 0000000000..529177010d --- /dev/null +++ b/examples/utilities/tools/render/AO.qml @@ -0,0 +1,101 @@ +// +// AO.qml +// examples/utilities/tools/render +// +// Created by Zach Pomerantz on 2/8/2016 +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html +// +import QtQuick 2.5 +import QtQuick.Controls 1.4 + +Item { + width: 200 + height: 200 + property QtObject config: Render.getConfig("AmbientOcclusion") + + Timer { + interval: 500 + running: true + repeat: true + onTriggered: { parent.timer.text = config.gpuTime.toFixed(2) } + } + + Label { text: qsTr("Ambient Occlusion") } + Label { id: timer; x: 140 } + + CheckBox { + y: 1 * 25 + text: qsTr("Dithering") + partiallyCheckedEnabled: false + checked: parent.config.ditheringEnabled + onCheckedChanged: { parent.config.ditheringEnabled = checked } + } + + ConfigSlider { + y: 2 * 25 + config: parent.config + prop: "resolutionLevel" + label: qsTr("Resolution Level") + min: 0; max: 4 + } + ConfigSlider { + y: 3 * 25 + config: parent.config + prop: "obscuranceLevel" + label: qsTr("Obscurance Level") + min: 0; max: 1 + } + ConfigSlider { + y: 4 * 25 + config: parent.config + prop: "radius" + label: qsTr("Radius") + min: 0; max: 2 + } + ConfigSlider { + y: 5 * 25 + config: parent.config + prop: "numSamples" + label: qsTr("Samples") + min: 0; max: 32 + } + ConfigSlider { + y: 6 * 25 + config: parent.config + prop: "numSpiralTurns" + label: qsTr("Spiral Turns") + min: 0; max: 30 + } + ConfigSlider { + y: 7 * 25 + config: parent.config + prop: "falloffBias" + label: qsTr("Falloff Bias") + min: 0; max: 0.2 + } + ConfigSlider { + y: 8 * 25 + config: parent.config + prop: "edgeSharpness" + label: qsTr("Edge Sharpness") + min: 0; max: 1 + } + ConfigSlider { + y: 9 * 25 + config: parent.config + prop: "blurRadius" + label: qsTr("Blur Radius") + min: 0; max: 6 + } + ConfigSlider { + y: 10 * 25 + config: parent.config + prop: "blurDeviation" + label: qsTr("Blur Deviation") + min: 0; max: 3 + } +} + diff --git a/examples/utilities/tools/render/Buffer.qml b/examples/utilities/tools/render/Buffer.qml new file mode 100644 index 0000000000..bc4b654257 --- /dev/null +++ b/examples/utilities/tools/render/Buffer.qml @@ -0,0 +1,99 @@ +// +// Buffer.qml +// examples/utilities/tools/render +// +// Created by Zach Pomerantz on 2/8/2016 +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html +// +import QtQuick 2.5 +import QtQuick.Controls 1.4 + +Item { + width: 200 + height: 270 + + Label { + text: qsTr("Debug Buffer") + } + + ExclusiveGroup { id: buffer } + + function setDebugMode(mode) { + var debug = Render.getConfig("DebugDeferredBuffer"); + console.log(mode); + debug.enabled = (mode != 0); + debug.mode = mode; + } + + RadioButton { + x: 8; y: 19 + 0 * 23 + text: qsTr("Off") + exclusiveGroup: buffer + checked: true + onCheckedChanged: { if (checked) { setDebugMode(0) } } + } + RadioButton { + x: 8; y: 19 + 1 * 23 + text: qsTr("Diffuse") + exclusiveGroup: buffer + onCheckedChanged: { if (checked) { setDebugMode(1) } } + } + RadioButton { + x: 8; y: 19 + 2 * 23 + text: qsTr("Metallic") + exclusiveGroup: buffer + onCheckedChanged: { if (checked) { setDebugMode(2) } } + } + RadioButton { + x: 8; y: 19 + 3 * 23 + text: qsTr("Roughness") + exclusiveGroup: buffer + onCheckedChanged: { if (checked) { setDebugMode(3) } } + } + RadioButton { + x: 8; y: 19 + 4 * 23 + text: qsTr("Normal") + exclusiveGroup: buffer + onCheckedChanged: { if (checked) { setDebugMode(4) } } + } + RadioButton { + x: 8; y: 19 + 5 * 23 + text: qsTr("Depth") + exclusiveGroup: buffer + onCheckedChanged: { if (checked) { setDebugMode(5) } } + } + RadioButton { + x: 8; y: 19 + 6 * 23 + text: qsTr("Lighting") + exclusiveGroup: buffer + onCheckedChanged: { if (checked) { setDebugMode(6) } } + } + RadioButton { + x: 8; y: 19 + 7 * 23 + text: qsTr("Shadow") + exclusiveGroup: buffer + onCheckedChanged: { if (checked) { setDebugMode(7) } } + } + RadioButton { + x: 8; y: 19 + 8 * 23 + text: qsTr("Pyramid Depth") + exclusiveGroup: buffer + onCheckedChanged: { if (checked) { setDebugMode(8) } } + } + RadioButton { + x: 8; y: 19 + 9 * 23 + text: qsTr("Ambient Occlusion") + exclusiveGroup: buffer + onCheckedChanged: { if (checked) { setDebugMode(9) } } + } + RadioButton { + x: 8; y: 19 + 10 * 23 + text: qsTr("Custom Shader") + exclusiveGroup: buffer + onCheckedChanged: { if (checked) { setDebugMode(10) } } + } +} + diff --git a/examples/utilities/tools/render/ConfigSlider.qml b/examples/utilities/tools/render/ConfigSlider.qml new file mode 100644 index 0000000000..7c6498a7d2 --- /dev/null +++ b/examples/utilities/tools/render/ConfigSlider.qml @@ -0,0 +1,58 @@ +// +// ConfigSlider.qml +// examples/utilities/tools/render +// +// Created by Zach Pomerantz on 2/8/2016 +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html +// +import QtQuick 2.5 +import QtQuick.Controls 1.4 + +Item { + width: 400 + height: 24 + property string label + property QtObject config + property string prop + property real min: 0.0 + property real max: 1.0 + + function init() { + stat.text = config[prop].toFixed(2); + slider.value = (config[prop] - min) / (max - min); + } + Component.onCompleted: init() + + function update() { + var val = min + (max - min) * slider.value; + stat.text = val.toFixed(2); + config[prop] = val; + } + + Label { + text: parent.label + y: 7 + anchors.left: parent.left + anchors.leftMargin: 8 + } + + Label { + id: stat + y: 7 + anchors.left: parent.left + anchors.leftMargin: 140 + } + + Slider { + id: slider + y: 3 + width: 192 + height: 20 + onValueChanged: parent.update() + anchors.right: parent.right + anchors.rightMargin: 8 + } +} diff --git a/examples/utilities/tools/render/ItemsSlider.qml b/examples/utilities/tools/render/ItemsSlider.qml new file mode 100644 index 0000000000..1623284579 --- /dev/null +++ b/examples/utilities/tools/render/ItemsSlider.qml @@ -0,0 +1,59 @@ +// +// ItemsSlider.qml +// examples/utilities/tools/render +// +// Created by Zach Pomerantz on 2/8/2016 +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html +// +import QtQuick 2.5 +import QtQuick.Controls 1.4 + +Item { + width: 400 + height: 24 + property string label + property QtObject config + + function update() { + var val = slider.value; + var max = config.numDrawn; + var drawn = Math.round(val * max); + stat.text = drawn + " / " + max; + config.maxDrawn = (val == 1.0 ? -1 : drawn); + } + + Timer { + interval: 500 + running: true + repeat: true + onTriggered: parent.update() + } + + Label { + text: parent.label + y: 7 + anchors.left: parent.left + anchors.leftMargin: 8 + } + + Label { + id: stat + y: 7 + anchors.left: parent.left + anchors.leftMargin: 108 + } + + Slider { + id: slider + y: 3 + width: 192 + height: 20 + value: 1.0 + onValueChanged: update() + anchors.right: parent.right + anchors.rightMargin: 8 + } +} diff --git a/examples/utilities/tools/render/Tone.qml b/examples/utilities/tools/render/Tone.qml new file mode 100644 index 0000000000..a0eb4b1e00 --- /dev/null +++ b/examples/utilities/tools/render/Tone.qml @@ -0,0 +1,49 @@ +// +// Tone.qml +// examples/utilities/tools/render +// +// Created by Zach Pomerantz on 2/8/2016 +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html +// +import QtQuick 2.5 +import QtQuick.Controls 1.4 + +Item { + width: 400 + height: 24 + property string label: qsTr("Tone Mapping Exposure") + + function update() { + var val = (slider.value - 0.5) * 20; + stat.text = val.toFixed(2); + Render.getConfig("ToneMapping").exposure = val; + } + + Label { + text: parent.label + y: 7 + anchors.left: parent.left + anchors.leftMargin: 8 + } + + Label { + id: stat + y: 7 + anchors.left: parent.left + anchors.leftMargin: 150 + } + + Slider { + id: slider + y: 3 + width: 192 + height: 20 + value: Render.getConfig("ToneMapping").exposure + onValueChanged: parent.update() + anchors.right: parent.right + anchors.rightMargin: 8 + } +} diff --git a/examples/utilities/tools/render/debug.js b/examples/utilities/tools/render/debug.js new file mode 100644 index 0000000000..896d2ac179 --- /dev/null +++ b/examples/utilities/tools/render/debug.js @@ -0,0 +1,38 @@ +// +// debug.js +// examples/utilities/tools/render +// +// Zach Pomerantz, created on 1/27/2016. +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +oldConfig = Render.toJSON(); +Render.RenderShadowTask.enabled = true; +Render.RenderDeferredTask.AmbientOcclusion.enabled = true; +Render.RenderDeferredTask.DebugDeferredBuffer.enabled = false; + +// Set up the qml ui +var qml = Script.resolvePath('main.qml'); +var window = new OverlayWindow({ + title: 'Render Engine Configuration', + source: qml, + width: 400, height: 900, +}); +window.setPosition(25, 50); +window.closed.connect(function() { Script.stop(); }); + +// Debug buffer sizing +var resizing = false; +Controller.mousePressEvent.connect(function() { resizing = true; }); +Controller.mouseReleaseEvent.connect(function() { resizing = false; }); +Controller.mouseMoveEvent.connect(function(e) { resizing && setDebugBufferSize(e.x); }); +function setDebugBufferSize(x) { + x = (2.0 * (x / Window.innerWidth) - 1.0); // scale + x = Math.min(Math.max(-1, x), 1); // clamp + Render.RenderDeferredTask.DebugDeferredBuffer.size = {x: x, y: -1, z: 1, w: 1}; +} + +Script.scriptEnding.connect(function() { Render.fromJSON(oldConfig); } ); diff --git a/examples/utilities/tools/render/main.qml b/examples/utilities/tools/render/main.qml new file mode 100644 index 0000000000..729e91c4f8 --- /dev/null +++ b/examples/utilities/tools/render/main.qml @@ -0,0 +1,64 @@ +// +// main.qml +// examples/utilities/tools/render +// +// Created by Zach Pomerantz on 2/8/2016 +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html +// +import QtQuick 2.5 +import QtQuick.Controls 1.4 + +Item { + // Items + ItemsSlider { + y: 0 * 25 + label: qsTr("Opaque") + config: Render.getConfig("DrawOpaqueDeferred") + } + ItemsSlider { + y: 1 * 25 + label: qsTr("Transparent") + config: Render.getConfig("DrawTransparentDeferred") + } + ItemsSlider { + y: 2 * 25 + label: qsTr("Overlay3D") + config: Render.getConfig("DrawOverlay3D") + } + + // Draw status + Item { + y: 100 + + CheckBox { + text: qsTr("Display Status") + partiallyCheckedEnabled: false + onCheckedChanged: { Render.getConfig("DrawStatus").showDisplay = checked } + } + CheckBox { + x: 200 + text: qsTr("Network/Physics Status") + partiallyCheckedEnabled: false + onCheckedChanged: { Render.getConfig("DrawStatus").showNetwork = checked } + } + } + + // Tone mapping + ConfigSlider { + y: 125 + config: Render.getConfig("ToneMapping") + prop: "exposure" + label: qsTr("Tone Mapping Exposure") + min: -10; max: 10 + } + + // Ambient occlusion + AO { y: 175 } + + // Debug buffer + Buffer { y: 475 } +} + diff --git a/examples/utilities/tools/renderEngineDebug.js b/examples/utilities/tools/renderEngineDebug.js deleted file mode 100755 index 5d38561eda..0000000000 --- a/examples/utilities/tools/renderEngineDebug.js +++ /dev/null @@ -1,216 +0,0 @@ -// -// renderEngineDebug.js -// examples/utilities/tools -// -// Sam Gateau -// Copyright 2015 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -Script.include("cookies.js"); - -var MENU = "Developer>Render>Debug Deferred Buffer"; -var ACTIONS = ["Off", "Diffuse", "Metallic", "Roughness", "Normal", "Depth", "Lighting", "Shadow", "PyramidDepth", "AmbientOcclusion", "OcclusionBlurred", "Custom"]; -var SETTINGS_KEY = "EngineDebugScript.DebugMode"; - -Number.prototype.clamp = function(min, max) { - return Math.min(Math.max(this, min), max); -}; - -var panel = new Panel(10, 100); - -function CounterWidget(parentPanel, name, counter) { - var subPanel = parentPanel.newSubPanel(name); - var widget = parentPanel.items[name]; - widget.editTitle({ width: 270 }); - - subPanel.newSlider('Max Drawn', -1, 1, - function(value) { counter.maxDrawn = value; }, // setter - function() { return counter.maxDrawn; }, // getter - function(value) { return value; }); - - var slider = subPanel.getWidget('Max Drawn'); - - this.update = function () { - var numDrawn = counter.numDrawn; // avoid double polling - var numMax = Math.max(numDrawn, 1); - var title = [ - ' ' + name, - numDrawn + ' / ' + counter.numFeed - ].join('\t'); - - widget.editTitle({ text: title }); - slider.setMaxValue(numMax); - }; -}; - -var opaquesCounter = new CounterWidget(panel, "Opaques", Render.opaque); -var transparentsCounter = new CounterWidget(panel, "Transparents", Render.transparent); -var overlaysCounter = new CounterWidget(panel, "Overlays", Render.overlay3D); - -var resizing = false; -var previousMode = Settings.getValue(SETTINGS_KEY, -1); -previousMode = 8; -Menu.addActionGroup(MENU, ACTIONS, ACTIONS[previousMode + 1]); -Render.deferredDebugMode = previousMode; -Render.deferredDebugSize = { x: 0.0, y: -1.0, z: 1.0, w: 1.0 }; // Reset to default size - -function setEngineDeferredDebugSize(eventX) { - var scaledX = (2.0 * (eventX / Window.innerWidth) - 1.0).clamp(-1.0, 1.0); - Render.deferredDebugSize = { x: scaledX, y: -1.0, z: 1.0, w: 1.0 }; -} -function shouldStartResizing(eventX) { - var x = Math.abs(eventX - Window.innerWidth * (1.0 + Render.deferredDebugSize.x) / 2.0); - var mode = Render.deferredDebugMode; - return mode !== -1 && x < 20; -} - -function menuItemEvent(menuItem) { - var index = ACTIONS.indexOf(menuItem); - if (index >= 0) { - Render.deferredDebugMode = (index - 1); - } -} - -// see libraries/render/src/render/Engine.h -var showDisplayStatusFlag = 1; -var showNetworkStatusFlag = 2; - -panel.newCheckbox("Display status", - function(value) { Render.displayItemStatus = (value ? - Render.displayItemStatus | showDisplayStatusFlag : - Render.displayItemStatus & ~showDisplayStatusFlag); }, - function() { return (Render.displayItemStatus & showDisplayStatusFlag) > 0; }, - function(value) { return (value & showDisplayStatusFlag) > 0; } -); - -panel.newCheckbox("Network/Physics status", - function(value) { Render.displayItemStatus = (value ? - Render.displayItemStatus | showNetworkStatusFlag : - Render.displayItemStatus & ~showNetworkStatusFlag); }, - function() { return (Render.displayItemStatus & showNetworkStatusFlag) > 0; }, - function(value) { return (value & showNetworkStatusFlag) > 0; } -); - -panel.newSlider("Tone Mapping Exposure", -10, 10, - function (value) { Render.tone.exposure = value; }, - function() { return Render.tone.exposure; }, - function (value) { return (value); }); - -panel.newSlider("Ambient Occlusion Resolution Level", 0.0, 4.0, - function (value) { Render.ambientOcclusion.resolutionLevel = value; }, - function() { return Render.ambientOcclusion.resolutionLevel; }, - function (value) { return (value); }); - -panel.newSlider("Ambient Occlusion Radius", 0.0, 2.0, - function (value) { Render.ambientOcclusion.radius = value; }, - function() { return Render.ambientOcclusion.radius; }, - function (value) { return (value.toFixed(2)); }); - -panel.newSlider("Ambient Occlusion Level", 0.0, 1.0, - function (value) { Render.ambientOcclusion.level = value; }, - function() { return Render.ambientOcclusion.level; }, - function (value) { return (value.toFixed(2)); }); - -panel.newSlider("Ambient Occlusion Num Samples", 1, 32, - function (value) { Render.ambientOcclusion.numSamples = value; }, - function() { return Render.ambientOcclusion.numSamples; }, - function (value) { return (value); }); - -panel.newSlider("Ambient Occlusion Num Spiral Turns", 0.0, 30.0, - function (value) { Render.ambientOcclusion.numSpiralTurns = value; }, - function() { return Render.ambientOcclusion.numSpiralTurns; }, - function (value) { return (value.toFixed(2)); }); - -panel.newCheckbox("Ambient Occlusion Dithering", - function (value) { Render.ambientOcclusion.ditheringEnabled = value; }, - function() { return Render.ambientOcclusion.ditheringEnabled; }, - function (value) { return (value); }); - -panel.newSlider("Ambient Occlusion Falloff Bias", 0.0, 0.2, - function (value) { Render.ambientOcclusion.falloffBias = value; }, - function() { return Render.ambientOcclusion.falloffBias; }, - function (value) { return (value.toFixed(2)); }); - -panel.newSlider("Ambient Occlusion Edge Sharpness", 0.0, 1.0, - function (value) { Render.ambientOcclusion.edgeSharpness = value; }, - function() { return Render.ambientOcclusion.edgeSharpness; }, - function (value) { return (value.toFixed(2)); }); - -panel.newSlider("Ambient Occlusion Blur Radius", 0.0, 6.0, - function (value) { Render.ambientOcclusion.blurRadius = value; }, - function() { return Render.ambientOcclusion.blurRadius; }, - function (value) { return (value); }); - -panel.newSlider("Ambient Occlusion Blur Deviation", 0.0, 3.0, - function (value) { Render.ambientOcclusion.blurDeviation = value; }, - function() { return Render.ambientOcclusion.blurDeviation; }, - function (value) { return (value.toFixed(2)); }); - - -panel.newSlider("Ambient Occlusion GPU time", 0.0, 10.0, - function (value) {}, - function() { return Render.ambientOcclusion.gpuTime; }, - function (value) { return (value.toFixed(2) + " ms"); }); - - -var tickTackPeriod = 500; - -function updateCounters() { - opaquesCounter.update(); - transparentsCounter.update(); - overlaysCounter.update(); - panel.update("Ambient Occlusion GPU time"); -} -Script.setInterval(updateCounters, tickTackPeriod); - -function mouseMoveEvent(event) { - if (resizing) { - setEngineDeferredDebugSize(event.x); - } else { - panel.mouseMoveEvent(event); - } -} - -function mousePressEvent(event) { - if (shouldStartResizing(event.x)) { - resizing = true; - } else { - panel.mousePressEvent(event); - } -} - -function mouseReleaseEvent(event) { - if (resizing) { - resizing = false; - } else { - panel.mouseReleaseEvent(event); - } -} - -Controller.mouseMoveEvent.connect(mouseMoveEvent); -Controller.mousePressEvent.connect(mousePressEvent); -Controller.mouseReleaseEvent.connect(mouseReleaseEvent); - -Menu.menuItemEvent.connect(menuItemEvent); - -function scriptEnding() { - panel.destroy(); - Menu.removeActionGroup(MENU); - // Reset - Settings.setValue(SETTINGS_KEY, Render.deferredDebugMode); - Render.deferredDebugMode = -1; - Render.deferredDebugSize = { x: 0.0, y: -1.0, z: 1.0, w: 1.0 }; - Render.opaque.maxDrawn = -1; - Render.transparent.maxDrawn = -1; - Render.overlay3D.maxDrawn = -1; -} -Script.scriptEnding.connect(scriptEnding); - - -// Collapse items -panel.mousePressEvent({ x: panel.x, y: panel.items["Overlays"].y}); -panel.mousePressEvent({ x: panel.x, y: panel.items["Transparents"].y}); -panel.mousePressEvent({ x: panel.x, y: panel.items["Opaques"].y}); From 86412c18900e9a396f5e2e9e825abd3f45ef884f Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Mon, 8 Feb 2016 12:30:16 -0800 Subject: [PATCH 4/6] Fix default debug buffer size --- libraries/render-utils/src/DebugDeferredBuffer.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/render-utils/src/DebugDeferredBuffer.h b/libraries/render-utils/src/DebugDeferredBuffer.h index ecc2012466..b31985d6a3 100644 --- a/libraries/render-utils/src/DebugDeferredBuffer.h +++ b/libraries/render-utils/src/DebugDeferredBuffer.h @@ -27,7 +27,7 @@ public: void setMode(int newMode); int mode{ 0 }; - glm::vec4 size{ 0.0f, 0.0f, 0.0f, 0.0f }; + glm::vec4 size{ 0.0f, -1.0f, 1.0f, 1.0f }; signals: void dirty(); }; From 9c5881345a9683f26623eda3bb656c8f05e74791 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Mon, 8 Feb 2016 12:34:45 -0800 Subject: [PATCH 5/6] Disable the AO gpuTimer pending cpp fix --- examples/utilities/tools/render/AO.qml | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/examples/utilities/tools/render/AO.qml b/examples/utilities/tools/render/AO.qml index 529177010d..fb2126befd 100644 --- a/examples/utilities/tools/render/AO.qml +++ b/examples/utilities/tools/render/AO.qml @@ -16,15 +16,16 @@ Item { height: 200 property QtObject config: Render.getConfig("AmbientOcclusion") - Timer { - interval: 500 - running: true - repeat: true - onTriggered: { parent.timer.text = config.gpuTime.toFixed(2) } - } + // TODO: Enable the gpuTimer when it is fixed in cpp + // Timer { + // interval: 500 + // running: true + // repeat: true + // onTriggered: { parent.timer.text = config.gpuTime.toFixed(2) } + // } + // Label { id: timer; x: 140 } Label { text: qsTr("Ambient Occlusion") } - Label { id: timer; x: 140 } CheckBox { y: 1 * 25 From 3bace3cdbb07636bc1d76764337cfbf57bef6a7e Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Tue, 9 Feb 2016 18:54:48 -0800 Subject: [PATCH 6/6] Rework the qml for brevity --- examples/utilities/tools/render/AO.qml | 102 ---------------- examples/utilities/tools/render/Buffer.qml | 99 ---------------- .../utilities/tools/render/ConfigSlider.qml | 58 +++++---- .../utilities/tools/render/ItemsSlider.qml | 59 ---------- examples/utilities/tools/render/Tone.qml | 49 -------- examples/utilities/tools/render/debug.js | 8 +- examples/utilities/tools/render/main.qml | 110 +++++++++++++----- .../render-utils/src/RenderDeferredTask.cpp | 6 +- .../render-utils/src/RenderDeferredTask.h | 20 +++- 9 files changed, 136 insertions(+), 375 deletions(-) delete mode 100644 examples/utilities/tools/render/AO.qml delete mode 100644 examples/utilities/tools/render/Buffer.qml delete mode 100644 examples/utilities/tools/render/ItemsSlider.qml delete mode 100644 examples/utilities/tools/render/Tone.qml diff --git a/examples/utilities/tools/render/AO.qml b/examples/utilities/tools/render/AO.qml deleted file mode 100644 index fb2126befd..0000000000 --- a/examples/utilities/tools/render/AO.qml +++ /dev/null @@ -1,102 +0,0 @@ -// -// AO.qml -// examples/utilities/tools/render -// -// Created by Zach Pomerantz on 2/8/2016 -// Copyright 2016 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html -// -import QtQuick 2.5 -import QtQuick.Controls 1.4 - -Item { - width: 200 - height: 200 - property QtObject config: Render.getConfig("AmbientOcclusion") - - // TODO: Enable the gpuTimer when it is fixed in cpp - // Timer { - // interval: 500 - // running: true - // repeat: true - // onTriggered: { parent.timer.text = config.gpuTime.toFixed(2) } - // } - // Label { id: timer; x: 140 } - - Label { text: qsTr("Ambient Occlusion") } - - CheckBox { - y: 1 * 25 - text: qsTr("Dithering") - partiallyCheckedEnabled: false - checked: parent.config.ditheringEnabled - onCheckedChanged: { parent.config.ditheringEnabled = checked } - } - - ConfigSlider { - y: 2 * 25 - config: parent.config - prop: "resolutionLevel" - label: qsTr("Resolution Level") - min: 0; max: 4 - } - ConfigSlider { - y: 3 * 25 - config: parent.config - prop: "obscuranceLevel" - label: qsTr("Obscurance Level") - min: 0; max: 1 - } - ConfigSlider { - y: 4 * 25 - config: parent.config - prop: "radius" - label: qsTr("Radius") - min: 0; max: 2 - } - ConfigSlider { - y: 5 * 25 - config: parent.config - prop: "numSamples" - label: qsTr("Samples") - min: 0; max: 32 - } - ConfigSlider { - y: 6 * 25 - config: parent.config - prop: "numSpiralTurns" - label: qsTr("Spiral Turns") - min: 0; max: 30 - } - ConfigSlider { - y: 7 * 25 - config: parent.config - prop: "falloffBias" - label: qsTr("Falloff Bias") - min: 0; max: 0.2 - } - ConfigSlider { - y: 8 * 25 - config: parent.config - prop: "edgeSharpness" - label: qsTr("Edge Sharpness") - min: 0; max: 1 - } - ConfigSlider { - y: 9 * 25 - config: parent.config - prop: "blurRadius" - label: qsTr("Blur Radius") - min: 0; max: 6 - } - ConfigSlider { - y: 10 * 25 - config: parent.config - prop: "blurDeviation" - label: qsTr("Blur Deviation") - min: 0; max: 3 - } -} - diff --git a/examples/utilities/tools/render/Buffer.qml b/examples/utilities/tools/render/Buffer.qml deleted file mode 100644 index bc4b654257..0000000000 --- a/examples/utilities/tools/render/Buffer.qml +++ /dev/null @@ -1,99 +0,0 @@ -// -// Buffer.qml -// examples/utilities/tools/render -// -// Created by Zach Pomerantz on 2/8/2016 -// Copyright 2016 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html -// -import QtQuick 2.5 -import QtQuick.Controls 1.4 - -Item { - width: 200 - height: 270 - - Label { - text: qsTr("Debug Buffer") - } - - ExclusiveGroup { id: buffer } - - function setDebugMode(mode) { - var debug = Render.getConfig("DebugDeferredBuffer"); - console.log(mode); - debug.enabled = (mode != 0); - debug.mode = mode; - } - - RadioButton { - x: 8; y: 19 + 0 * 23 - text: qsTr("Off") - exclusiveGroup: buffer - checked: true - onCheckedChanged: { if (checked) { setDebugMode(0) } } - } - RadioButton { - x: 8; y: 19 + 1 * 23 - text: qsTr("Diffuse") - exclusiveGroup: buffer - onCheckedChanged: { if (checked) { setDebugMode(1) } } - } - RadioButton { - x: 8; y: 19 + 2 * 23 - text: qsTr("Metallic") - exclusiveGroup: buffer - onCheckedChanged: { if (checked) { setDebugMode(2) } } - } - RadioButton { - x: 8; y: 19 + 3 * 23 - text: qsTr("Roughness") - exclusiveGroup: buffer - onCheckedChanged: { if (checked) { setDebugMode(3) } } - } - RadioButton { - x: 8; y: 19 + 4 * 23 - text: qsTr("Normal") - exclusiveGroup: buffer - onCheckedChanged: { if (checked) { setDebugMode(4) } } - } - RadioButton { - x: 8; y: 19 + 5 * 23 - text: qsTr("Depth") - exclusiveGroup: buffer - onCheckedChanged: { if (checked) { setDebugMode(5) } } - } - RadioButton { - x: 8; y: 19 + 6 * 23 - text: qsTr("Lighting") - exclusiveGroup: buffer - onCheckedChanged: { if (checked) { setDebugMode(6) } } - } - RadioButton { - x: 8; y: 19 + 7 * 23 - text: qsTr("Shadow") - exclusiveGroup: buffer - onCheckedChanged: { if (checked) { setDebugMode(7) } } - } - RadioButton { - x: 8; y: 19 + 8 * 23 - text: qsTr("Pyramid Depth") - exclusiveGroup: buffer - onCheckedChanged: { if (checked) { setDebugMode(8) } } - } - RadioButton { - x: 8; y: 19 + 9 * 23 - text: qsTr("Ambient Occlusion") - exclusiveGroup: buffer - onCheckedChanged: { if (checked) { setDebugMode(9) } } - } - RadioButton { - x: 8; y: 19 + 10 * 23 - text: qsTr("Custom Shader") - exclusiveGroup: buffer - onCheckedChanged: { if (checked) { setDebugMode(10) } } - } -} - diff --git a/examples/utilities/tools/render/ConfigSlider.qml b/examples/utilities/tools/render/ConfigSlider.qml index 7c6498a7d2..5ee62dfe49 100644 --- a/examples/utilities/tools/render/ConfigSlider.qml +++ b/examples/utilities/tools/render/ConfigSlider.qml @@ -12,47 +12,55 @@ import QtQuick 2.5 import QtQuick.Controls 1.4 Item { + id: root width: 400 height: 24 - property string label - property QtObject config - property string prop - property real min: 0.0 - property real max: 1.0 + property bool integral: false + property var config + property string property + property alias label: labelControl.text + property alias min: sliderControl.minimumValue + property alias max: sliderControl.maximumValue - function init() { - stat.text = config[prop].toFixed(2); - slider.value = (config[prop] - min) / (max - min); - } - Component.onCompleted: init() - - function update() { - var val = min + (max - min) * slider.value; - stat.text = val.toFixed(2); - config[prop] = val; + Component.onCompleted: { + // Binding favors qml value, so set it first + sliderControl.value = root.config[root.property]; + bindingControl.when = true; } Label { - text: parent.label - y: 7 - anchors.left: parent.left + id: labelControl + text: root.label + anchors.left: root.left anchors.leftMargin: 8 + anchors.top: root.top + anchors.topMargin: 7 } Label { - id: stat - y: 7 - anchors.left: parent.left + text: sliderControl.value.toFixed(root.integral ? 0 : 2) + anchors.left: root.left anchors.leftMargin: 140 + anchors.top: root.top + anchors.topMargin: 7 + } + + Binding { + id: bindingControl + target: root.config + property: root.property + value: sliderControl.value + when: false } Slider { - id: slider - y: 3 + id: sliderControl + stepSize: root.integral ? 1.0 : 0.0 width: 192 height: 20 - onValueChanged: parent.update() - anchors.right: parent.right + anchors.right: root.right anchors.rightMargin: 8 + anchors.top: root.top + anchors.topMargin: 3 } } diff --git a/examples/utilities/tools/render/ItemsSlider.qml b/examples/utilities/tools/render/ItemsSlider.qml deleted file mode 100644 index 1623284579..0000000000 --- a/examples/utilities/tools/render/ItemsSlider.qml +++ /dev/null @@ -1,59 +0,0 @@ -// -// ItemsSlider.qml -// examples/utilities/tools/render -// -// Created by Zach Pomerantz on 2/8/2016 -// Copyright 2016 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html -// -import QtQuick 2.5 -import QtQuick.Controls 1.4 - -Item { - width: 400 - height: 24 - property string label - property QtObject config - - function update() { - var val = slider.value; - var max = config.numDrawn; - var drawn = Math.round(val * max); - stat.text = drawn + " / " + max; - config.maxDrawn = (val == 1.0 ? -1 : drawn); - } - - Timer { - interval: 500 - running: true - repeat: true - onTriggered: parent.update() - } - - Label { - text: parent.label - y: 7 - anchors.left: parent.left - anchors.leftMargin: 8 - } - - Label { - id: stat - y: 7 - anchors.left: parent.left - anchors.leftMargin: 108 - } - - Slider { - id: slider - y: 3 - width: 192 - height: 20 - value: 1.0 - onValueChanged: update() - anchors.right: parent.right - anchors.rightMargin: 8 - } -} diff --git a/examples/utilities/tools/render/Tone.qml b/examples/utilities/tools/render/Tone.qml deleted file mode 100644 index a0eb4b1e00..0000000000 --- a/examples/utilities/tools/render/Tone.qml +++ /dev/null @@ -1,49 +0,0 @@ -// -// Tone.qml -// examples/utilities/tools/render -// -// Created by Zach Pomerantz on 2/8/2016 -// Copyright 2016 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html -// -import QtQuick 2.5 -import QtQuick.Controls 1.4 - -Item { - width: 400 - height: 24 - property string label: qsTr("Tone Mapping Exposure") - - function update() { - var val = (slider.value - 0.5) * 20; - stat.text = val.toFixed(2); - Render.getConfig("ToneMapping").exposure = val; - } - - Label { - text: parent.label - y: 7 - anchors.left: parent.left - anchors.leftMargin: 8 - } - - Label { - id: stat - y: 7 - anchors.left: parent.left - anchors.leftMargin: 150 - } - - Slider { - id: slider - y: 3 - width: 192 - height: 20 - value: Render.getConfig("ToneMapping").exposure - onValueChanged: parent.update() - anchors.right: parent.right - anchors.rightMargin: 8 - } -} diff --git a/examples/utilities/tools/render/debug.js b/examples/utilities/tools/render/debug.js index 896d2ac179..f195c607a4 100644 --- a/examples/utilities/tools/render/debug.js +++ b/examples/utilities/tools/render/debug.js @@ -11,8 +11,12 @@ oldConfig = Render.toJSON(); Render.RenderShadowTask.enabled = true; -Render.RenderDeferredTask.AmbientOcclusion.enabled = true; -Render.RenderDeferredTask.DebugDeferredBuffer.enabled = false; +var RDT = Render.RenderDeferredTask; +RDT.AmbientOcclusion.enabled = true; +RDT.DebugDeferredBuffer.enabled = false; +["DrawOpaqueDeferred", "DrawTransparentDeferred", "DrawOverlay3DOpaque", "DrawOverlay3DTransparent"] + .map(function(name) { return RDT[name]; }) + .forEach(function(job) { job.maxDrawn = job.numDrawn; }); // Set up the qml ui var qml = Script.resolvePath('main.qml'); diff --git a/examples/utilities/tools/render/main.qml b/examples/utilities/tools/render/main.qml index 729e91c4f8..9e825ad4df 100644 --- a/examples/utilities/tools/render/main.qml +++ b/examples/utilities/tools/render/main.qml @@ -11,54 +11,100 @@ import QtQuick 2.5 import QtQuick.Controls 1.4 -Item { - // Items - ItemsSlider { - y: 0 * 25 - label: qsTr("Opaque") - config: Render.getConfig("DrawOpaqueDeferred") - } - ItemsSlider { - y: 1 * 25 - label: qsTr("Transparent") - config: Render.getConfig("DrawTransparentDeferred") - } - ItemsSlider { - y: 2 * 25 - label: qsTr("Overlay3D") - config: Render.getConfig("DrawOverlay3D") +Column { + spacing: 8 + + Repeater { + model: [ "Opaque:DrawOpaqueDeferred", "Transparent:DrawTransparentDeferred", + "Opaque Overlays:DrawOverlay3DOpaque", "Transparent Overlays:DrawOverlay3DTransparent" ] + ConfigSlider { + label: qsTr(modelData.split(":")[0]) + integral: true + config: Render.getConfig(modelData.split(":")[1]) + property: "maxDrawn" + max: config.numDrawn + } } - // Draw status - Item { - y: 100 - + Row { CheckBox { text: qsTr("Display Status") - partiallyCheckedEnabled: false onCheckedChanged: { Render.getConfig("DrawStatus").showDisplay = checked } } CheckBox { - x: 200 text: qsTr("Network/Physics Status") - partiallyCheckedEnabled: false onCheckedChanged: { Render.getConfig("DrawStatus").showNetwork = checked } } } - // Tone mapping ConfigSlider { - y: 125 - config: Render.getConfig("ToneMapping") - prop: "exposure" label: qsTr("Tone Mapping Exposure") + config: Render.getConfig("ToneMapping") + property: "exposure" min: -10; max: 10 } - // Ambient occlusion - AO { y: 175 } + Column { + id: ambientOcclusion + property var config: Render.getConfig("AmbientOcclusion") - // Debug buffer - Buffer { y: 475 } + Label { text: qsTr("Ambient Occlusion") } + // TODO: Add gpuTimer + CheckBox { text: qsTr("Dithering"); checked: ambientOcclusion.config.ditheringEnabled } + Repeater { + model: [ + "Resolution Level:resolutionLevel:4", + "Obscurance Level:obscuranceLevel:1", + "Radius:radius:2", + "Falloff Bias:falloffBias:0.2", + "Edge Sharpness:edgeSharpness:1", + "Blur Radius:blurRadius:6", + "Blur Deviation:blurDeviation:3" + ] + ConfigSlider { + label: qsTr(modelData.split(":")[0]) + config: ambientOcclusion.config + property: modelData.split(":")[1] + max: modelData.split(":")[2] + } + } + Repeater { + model: [ + "Samples:numSamples:32", + "Spiral Turns:numSpiralTurns:30:" + ] + ConfigSlider { + label: qsTr(modelData.split(":")[0]) + integral: true + config: ambientOcclusion.config + property: modelData.split(":")[1] + max: modelData.split(":")[2] + } + } + } + + Column { + id: debug + property var config: Render.getConfig("DebugDeferredBuffer") + + function setDebugMode(mode) { + debug.config.enabled = (mode != 0); + debug.config.mode = mode; + } + + Label { text: qsTr("Debug Buffer") } + ExclusiveGroup { id: bufferGroup } + Repeater { + model: [ + "Off", "Diffuse", "Metallic", "Roughness", "Normal", "Depth", + "Lighting", "Shadow", "Pyramid Depth", "Ambient Occlusion", "Custom Shader" + ] + RadioButton { + text: qsTr(modelData) + exclusiveGroup: bufferGroup + checked: index == 0 + onCheckedChanged: if (checked) debug.setDebugMode(index); + } + } + } } - diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index d3aeb23a50..30a49f93d5 100755 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -142,7 +142,8 @@ void DrawDeferred::run(const SceneContextPointer& sceneContext, const RenderCont batch.setStateScissorRect(args->_viewport); args->_batch = &batch; - config->numDrawn = (int)inItems.size(); + config->setNumDrawn((int)inItems.size()); + emit config->numDrawnChanged(); glm::mat4 projMat; Transform viewMat; @@ -179,7 +180,8 @@ void DrawOverlay3D::run(const SceneContextPointer& sceneContext, const RenderCon inItems.emplace_back(id); } } - config->numItems = (int)inItems.size(); + config->setNumDrawn((int)inItems.size()); + emit config->numDrawnChanged(); if (!inItems.empty()) { RenderArgs* args = renderContext->args; diff --git a/libraries/render-utils/src/RenderDeferredTask.h b/libraries/render-utils/src/RenderDeferredTask.h index 5d97de3905..3d072bce7b 100755 --- a/libraries/render-utils/src/RenderDeferredTask.h +++ b/libraries/render-utils/src/RenderDeferredTask.h @@ -40,15 +40,20 @@ public: class DrawConfig : public render::Job::Config { Q_OBJECT - Q_PROPERTY(int numDrawn READ getNumDrawn) + Q_PROPERTY(int numDrawn READ getNumDrawn NOTIFY numDrawnChanged) Q_PROPERTY(int maxDrawn MEMBER maxDrawn NOTIFY dirty) public: int getNumDrawn() { return numDrawn; } + void setNumDrawn(int num) { numDrawn = num; emit numDrawnChanged(); } - int numDrawn{ 0 }; int maxDrawn{ -1 }; + signals: + void numDrawnChanged(); void dirty(); + +protected: + int numDrawn{ 0 }; }; class DrawDeferred { @@ -86,15 +91,20 @@ public: class DrawOverlay3DConfig : public render::Job::Config { Q_OBJECT - Q_PROPERTY(int numItems READ getNumItems) + Q_PROPERTY(int numDrawn READ getNumDrawn NOTIFY numDrawnChanged) Q_PROPERTY(int maxDrawn MEMBER maxDrawn NOTIFY dirty) public: - int getNumItems() { return numItems; } + int getNumDrawn() { return numDrawn; } + void setNumDrawn(int num) { numDrawn = num; emit numDrawnChanged(); } - int numItems{ 0 }; int maxDrawn{ -1 }; + signals: + void numDrawnChanged(); void dirty(); + +protected: + int numDrawn{ 0 }; }; class DrawOverlay3D {