wip hud layering and fix crashes

This commit is contained in:
SamGondelman 2017-10-04 11:45:21 -07:00
parent fa838e4715
commit 477dfdff1e
13 changed files with 111 additions and 47 deletions

View file

@ -88,6 +88,10 @@ void ModelOverlay::update(float deltatime) {
_drawInFrontDirty = false; _drawInFrontDirty = false;
_model->setLayeredInFront(getDrawInFront(), scene); _model->setLayeredInFront(getDrawInFront(), scene);
} }
if (_drawInHUDDirty) {
_drawInHUDDirty = false;
_model->setLayeredInHUD(getDrawHUDLayer(), scene);
}
scene->enqueueTransaction(transaction); scene->enqueueTransaction(transaction);
} }
@ -112,6 +116,11 @@ void ModelOverlay::setDrawInFront(bool drawInFront) {
_drawInFrontDirty = true; _drawInFrontDirty = true;
} }
void ModelOverlay::setDrawHUDLayer(bool drawHUDLayer) {
Base3DOverlay::setDrawHUDLayer(drawHUDLayer);
_drawInHUDDirty = true;
}
void ModelOverlay::setProperties(const QVariantMap& properties) { void ModelOverlay::setProperties(const QVariantMap& properties) {
auto origPosition = getPosition(); auto origPosition = getPosition();
auto origRotation = getRotation(); auto origRotation = getRotation();

View file

@ -51,6 +51,7 @@ public:
void setVisible(bool visible) override; void setVisible(bool visible) override;
void setDrawInFront(bool drawInFront) override; void setDrawInFront(bool drawInFront) override;
void setDrawHUDLayer(bool drawHUDLayer) override;
protected: protected:
Transform evalRenderTransform() override; Transform evalRenderTransform() override;
@ -98,6 +99,7 @@ private:
bool _visibleDirty { false }; bool _visibleDirty { false };
bool _drawInFrontDirty { false }; bool _drawInFrontDirty { false };
bool _drawInHUDDirty { false };
}; };

View file

@ -50,20 +50,17 @@ namespace render {
return overlay->getBounds(); return overlay->getBounds();
} }
template <> int payloadGetLayer(const Overlay::Pointer& overlay) { template <> int payloadGetLayer(const Overlay::Pointer& overlay) {
// Magic number while we are defining the layering mechanism:
const int LAYER_2D = 2;
const int LAYER_3D_FRONT = 1;
const int LAYER_3D = 0;
if (overlay->is3D()) { if (overlay->is3D()) {
auto overlay3D = std::dynamic_pointer_cast<Base3DOverlay>(overlay); auto overlay3D = std::dynamic_pointer_cast<Base3DOverlay>(overlay);
if (overlay3D->getDrawInFront()) { if (overlay3D->getDrawInFront()) {
return LAYER_3D_FRONT; return Item::LAYER_3D_FRONT;
} else if (overlay3D->getDrawHUDLayer()) {
return Item::LAYER_3D_HUD;
} else { } else {
return LAYER_3D; return Item::LAYER_3D;
} }
} else { } else {
return LAYER_2D; return Item::LAYER_2D;
} }
} }
template <> void payloadRender(const Overlay::Pointer& overlay, RenderArgs* args) { template <> void payloadRender(const Overlay::Pointer& overlay, RenderArgs* args) {

View file

@ -569,11 +569,11 @@ std::function<void(gpu::Batch&, const gpu::TexturePointer&)> OpenGLDisplayPlugin
batch.setResourceTexture(0, hudTexture); batch.setResourceTexture(0, hudTexture);
if (isStereo()) { if (isStereo()) {
for_each_eye([&](Eye eye) { for_each_eye([&](Eye eye) {
batch.setViewportTransform(eyeViewport(eye)); batch.setViewportTransform(eyeViewport(eye, getRecommendedRenderSize()));
batch.draw(gpu::TRIANGLE_STRIP, 4); batch.draw(gpu::TRIANGLE_STRIP, 4);
}); });
} else { } else {
batch.setViewportTransform(ivec4(uvec2(0), _compositeFramebuffer->getSize())); batch.setViewportTransform(ivec4(uvec2(0), getRecommendedRenderSize()));
batch.draw(gpu::TRIANGLE_STRIP, 4); batch.draw(gpu::TRIANGLE_STRIP, 4);
} }
}; };
@ -838,6 +838,15 @@ ivec4 OpenGLDisplayPlugin::eyeViewport(Eye eye) const {
return ivec4(vpPos, vpSize); return ivec4(vpPos, vpSize);
} }
ivec4 OpenGLDisplayPlugin::eyeViewport(Eye eye, uvec2 vpSize) const {
vpSize.x /= 2;
uvec2 vpPos;
if (eye == Eye::Right) {
vpPos.x = vpSize.x;
}
return ivec4(vpPos, vpSize);
}
gpu::gl::GLBackend* OpenGLDisplayPlugin::getGLBackend() { gpu::gl::GLBackend* OpenGLDisplayPlugin::getGLBackend() {
if (!_gpuContext || !_gpuContext->getBackend()) { if (!_gpuContext || !_gpuContext->getBackend()) {
return nullptr; return nullptr;

View file

@ -125,6 +125,7 @@ protected:
void present(); void present();
virtual void swapBuffers(); virtual void swapBuffers();
ivec4 eyeViewport(Eye eye) const; ivec4 eyeViewport(Eye eye) const;
ivec4 eyeViewport(Eye eye, uvec2 vpSize) const;
void render(std::function<void(gpu::Batch& batch)> f); void render(std::function<void(gpu::Batch& batch)> f);

View file

@ -430,23 +430,25 @@ void HmdDisplayPlugin::HUDRenderer::updatePipeline() {
std::function<void(gpu::Batch&, const gpu::TexturePointer&)> HmdDisplayPlugin::HUDRenderer::render(HmdDisplayPlugin& plugin) { std::function<void(gpu::Batch&, const gpu::TexturePointer&)> HmdDisplayPlugin::HUDRenderer::render(HmdDisplayPlugin& plugin) {
updatePipeline(); updatePipeline();
return [this](gpu::Batch& batch, const gpu::TexturePointer& hudTexture) { return [this](gpu::Batch& batch, const gpu::TexturePointer& hudTexture) {
batch.setPipeline(pipeline); if (pipeline) {
batch.setInputFormat(format); batch.setPipeline(pipeline);
gpu::BufferView posView(vertices, VERTEX_OFFSET, vertices->getSize(), VERTEX_STRIDE, format->getAttributes().at(gpu::Stream::POSITION)._element); batch.setInputFormat(format);
gpu::BufferView uvView(vertices, TEXTURE_OFFSET, vertices->getSize(), VERTEX_STRIDE, format->getAttributes().at(gpu::Stream::TEXCOORD)._element); gpu::BufferView posView(vertices, VERTEX_OFFSET, vertices->getSize(), VERTEX_STRIDE, format->getAttributes().at(gpu::Stream::POSITION)._element);
batch.setInputBuffer(gpu::Stream::POSITION, posView); gpu::BufferView uvView(vertices, TEXTURE_OFFSET, vertices->getSize(), VERTEX_STRIDE, format->getAttributes().at(gpu::Stream::TEXCOORD)._element);
batch.setInputBuffer(gpu::Stream::TEXCOORD, uvView); batch.setInputBuffer(gpu::Stream::POSITION, posView);
batch.setIndexBuffer(gpu::UINT16, indices, 0); batch.setInputBuffer(gpu::Stream::TEXCOORD, uvView);
batch.setIndexBuffer(gpu::UINT16, indices, 0);
uniformsBuffer->setSubData(0, uniforms); uniformsBuffer->setSubData(0, uniforms);
batch.setUniformBuffer(uniformsLocation, uniformsBuffer); batch.setUniformBuffer(uniformsLocation, uniformsBuffer);
auto compositorHelper = DependencyManager::get<CompositorHelper>(); auto compositorHelper = DependencyManager::get<CompositorHelper>();
batch.setModelTransform(compositorHelper->getUiTransform()); batch.setModelTransform(compositorHelper->getUiTransform());
batch.setResourceTexture(0, hudTexture); batch.setResourceTexture(0, hudTexture);
batch.drawIndexed(gpu::TRIANGLES, indexCount); batch.drawIndexed(gpu::TRIANGLES, indexCount);
}
}; };
} }

View file

@ -404,15 +404,15 @@ ItemKey ModelMeshPartPayload::getKey() const {
} }
int ModelMeshPartPayload::getLayer() const { int ModelMeshPartPayload::getLayer() const {
// MAgic number while we are defining the layering mechanism:
const int LAYER_3D_FRONT = 1;
const int LAYER_3D = 0;
ModelPointer model = _model.lock(); ModelPointer model = _model.lock();
if (model && model->isLayeredInFront()) { if (model) {
return LAYER_3D_FRONT; if (model->isLayeredInFront()) {
} else { return Item::LAYER_3D_FRONT;
return LAYER_3D; } else if (model->isLayeredInHUD()) {
return Item::LAYER_3D_HUD;
}
} }
return Item::LAYER_3D;
} }
ShapeKey ModelMeshPartPayload::getShapeKey() const { ShapeKey ModelMeshPartPayload::getShapeKey() const {

View file

@ -598,6 +598,21 @@ void Model::setLayeredInFront(bool layered, const render::ScenePointer& scene) {
} }
} }
void Model::setLayeredInHUD(bool layered, const render::ScenePointer& scene) {
if (_isLayeredInHUD != layered) {
_isLayeredInHUD = layered;
render::Transaction transaction;
foreach(auto item, _modelMeshRenderItemsMap.keys()) {
transaction.resetItem(item, _modelMeshRenderItemsMap[item]);
}
foreach(auto item, _collisionRenderItemsMap.keys()) {
transaction.resetItem(item, _collisionRenderItemsMap[item]);
}
scene->enqueueTransaction(transaction);
}
}
bool Model::addToScene(const render::ScenePointer& scene, bool Model::addToScene(const render::ScenePointer& scene,
render::Transaction& transaction, render::Transaction& transaction,
render::Item::Status::Getters& statusGetters) { render::Item::Status::Getters& statusGetters) {

View file

@ -84,6 +84,7 @@ public:
// new Scene/Engine rendering support // new Scene/Engine rendering support
void setVisibleInScene(bool newValue, const render::ScenePointer& scene); void setVisibleInScene(bool newValue, const render::ScenePointer& scene);
void setLayeredInFront(bool layered, const render::ScenePointer& scene); void setLayeredInFront(bool layered, const render::ScenePointer& scene);
void setLayeredInHUD(bool layered, const render::ScenePointer& scene);
bool needsFixupInScene() const; bool needsFixupInScene() const;
bool needsReload() const { return _needsReload; } bool needsReload() const { return _needsReload; }

View file

@ -187,14 +187,19 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren
} }
// Overlays // Overlays
const auto overlayOpaquesInputs = DrawOverlay3D::Inputs(overlayOpaques, lightingModel).asVarying(); const auto filteredOverlaysOpaque = task.addJob<FilterLayeredItems>("FilterOverlaysLayeredOpaque", overlayOpaques, Item::LAYER_3D_FRONT);
const auto overlayTransparentsInputs = DrawOverlay3D::Inputs(overlayTransparents, lightingModel).asVarying(); const auto filteredOverlaysTransparent = task.addJob<FilterLayeredItems>("FilterOverlaysLayeredTransparent", overlayTransparents, Item::LAYER_3D_FRONT);
task.addJob<DrawOverlay3D>("DrawOverlay3DOpaque", overlayOpaquesInputs, true); const auto overlaysInFrontOpaque = filteredOverlaysOpaque.getN<FilterLayeredItems::Outputs>(0);
task.addJob<DrawOverlay3D>("DrawOverlay3DTransparent", overlayTransparentsInputs, false); const auto overlaysInFrontTransparent = filteredOverlaysTransparent.getN<FilterLayeredItems::Outputs>(0);
{ // Debug the bounds of the rendered Overlay items, still look at the zbuffer const auto overlayInFrontOpaquesInputs = DrawOverlay3D::Inputs(overlaysInFrontOpaque, lightingModel).asVarying();
task.addJob<DrawBounds>("DrawOverlayOpaqueBounds", overlayOpaques); const auto overlayInFrontTransparentsInputs = DrawOverlay3D::Inputs(overlaysInFrontTransparent, lightingModel).asVarying();
task.addJob<DrawBounds>("DrawOverlayTransparentBounds", overlayTransparents); 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);
} }
// Debugging stages // Debugging stages
@ -233,9 +238,22 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren
// AA job to be revisited // AA job to be revisited
task.addJob<Antialiasing>("Antialiasing", primaryFramebuffer); task.addJob<Antialiasing>("Antialiasing", primaryFramebuffer);
// Composite the HUD // Composite the HUD and HUD overlays
task.addJob<CompositeHUD>("HUD"); task.addJob<CompositeHUD>("HUD");
const auto overlaysHUDOpaque = filteredOverlaysOpaque.getN<FilterLayeredItems::Outputs>(1);
const auto overlaysHUDTransparent = filteredOverlaysTransparent.getN<FilterLayeredItems::Outputs>(1);
const auto overlayHUDOpaquesInputs = DrawOverlay3D::Inputs(overlaysHUDOpaque, lightingModel).asVarying();
const auto overlayHUDTransparentsInputs = DrawOverlay3D::Inputs(overlaysHUDTransparent, lightingModel).asVarying();
task.addJob<DrawOverlay3D>("DrawOverlayHUDOpaque", overlayHUDOpaquesInputs, true);
task.addJob<DrawOverlay3D>("DrawOverlayHUDTransparent", overlayHUDTransparentsInputs, false);
{ // Debug the bounds of the rendered Overlay items that are marked drawHUDLayer, still look at the zbuffer
task.addJob<DrawBounds>("DrawOverlayHUDOpaqueBounds", overlaysHUDOpaque);
task.addJob<DrawBounds>("DrawOverlayHUDOpaqueBounds", overlaysHUDTransparent);
}
task.addJob<EndGPURangeTimer>("ToneAndPostRangeTimer", toneAndPostRangeTimer); task.addJob<EndGPURangeTimer>("ToneAndPostRangeTimer", toneAndPostRangeTimer);
// Blit! // Blit!

View file

@ -21,19 +21,24 @@
using namespace render; using namespace render;
void FilterLayeredItems::run(const RenderContextPointer& renderContext, const ItemBounds& inItems, ItemBounds& outItems) { void FilterLayeredItems::run(const RenderContextPointer& renderContext, const ItemBounds& inItems, Outputs& outputs) {
auto& scene = renderContext->_scene; auto& scene = renderContext->_scene;
// Clear previous values ItemBounds matchedItems;
outItems.clear(); ItemBounds nonMatchItems;
// For each item, filter it into one bucket // For each item, filter it into one bucket
for (auto& itemBound : inItems) { for (auto& itemBound : inItems) {
auto& item = scene->getItem(itemBound.id); auto& item = scene->getItem(itemBound.id);
if (item.getLayer() == _keepLayer) { if (item.getLayer() == _keepLayer) {
outItems.emplace_back(itemBound); matchedItems.emplace_back(itemBound);
} else {
nonMatchItems.emplace_back(itemBound);
} }
} }
outputs.edit0() = matchedItems;
outputs.edit1() = nonMatchItems;
} }
void SliceItems::run(const RenderContextPointer& renderContext, const ItemBounds& inItems, ItemBounds& outItems) { void SliceItems::run(const RenderContextPointer& renderContext, const ItemBounds& inItems, ItemBounds& outItems) {

View file

@ -65,15 +65,15 @@ namespace render {
// Filter the items belonging to the job's keep layer // Filter the items belonging to the job's keep layer
class FilterLayeredItems { class FilterLayeredItems {
public: public:
using JobModel = Job::ModelIO<FilterLayeredItems, ItemBounds, ItemBounds>; using Outputs = render::VaryingSet2<ItemBounds, ItemBounds>;
using JobModel = Job::ModelIO<FilterLayeredItems, ItemBounds, Outputs>;
FilterLayeredItems() {}
FilterLayeredItems(int keepLayer) : FilterLayeredItems(int keepLayer) :
_keepLayer(keepLayer) {} _keepLayer(keepLayer) {}
int _keepLayer { 0 }; int _keepLayer;
void run(const RenderContextPointer& renderContext, const ItemBounds& inItems, ItemBounds& outItems); void run(const RenderContextPointer& renderContext, const ItemBounds& inItems, Outputs& outputs);
}; };
// SliceItems job config defining the slice range // SliceItems job config defining the slice range

View file

@ -356,9 +356,14 @@ public:
// Get the bound of the item expressed in world space (or eye space depending on the key.isWorldSpace()) // Get the bound of the item expressed in world space (or eye space depending on the key.isWorldSpace())
const Bound getBound() const { return _payload->getBound(); } const Bound getBound() const { return _payload->getBound(); }
// Get the layer where the item belongs. 0 by default meaning NOT LAYERED // Get the layer where the item belongs.
int getLayer() const { return _payload->getLayer(); } int getLayer() const { return _payload->getLayer(); }
static const int LAYER_2D = 0;
static const int LAYER_3D = 1;
static const int LAYER_3D_FRONT = 2;
static const int LAYER_3D_HUD = 3;
// Render call for the item // Render call for the item
void render(RenderArgs* args) const { _payload->render(args); } void render(RenderArgs* args) const { _payload->render(args); }