diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 14a64d289e..c5c92837bf 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -177,7 +177,22 @@ bool RenderableModelEntityItem::addToScene(EntityItemPointer self, std::shared_p pendingChanges.resetItem(_myMetaItem, renderPayload); if (_model) { - return _model->addToScene(scene, pendingChanges); + // return _model->addToScene(scene, pendingChanges); + + render::Item::Status::Getter statusGetter = [this] () -> render::Item::Status::Value { + quint64 now = usecTimestampNow(); + /* if (now - entity->getLastEditedFromRemote() < 0.1f * USECS_PER_SECOND) { + return glm::vec4 redColor(1.0f, 0.0f, 0.0f, 1.0f); + renderBoundingBox(entity, args, 0.16f, redColor); + } + */ + if (now - this->getLastBroadcast() < 0.2f * USECS_PER_SECOND) { + return 256; + } + return 0; + }; + return _model->addToScene(scene, pendingChanges, statusGetter); + } return true; diff --git a/libraries/gpu/src/gpu/GLBackend.cpp b/libraries/gpu/src/gpu/GLBackend.cpp index 112e34eaea..b7b2744c31 100644 --- a/libraries/gpu/src/gpu/GLBackend.cpp +++ b/libraries/gpu/src/gpu/GLBackend.cpp @@ -191,6 +191,18 @@ void GLBackend::do_drawIndexed(Batch& batch, uint32 paramOffset) { } void GLBackend::do_drawInstanced(Batch& batch, uint32 paramOffset) { + updateInput(); + updateTransform(); + updatePipeline(); + + GLint numInstances = batch._params[paramOffset + 4]._uint; + Primitive primitiveType = (Primitive)batch._params[paramOffset + 3]._uint; + GLenum mode = _primitiveToGLmode[primitiveType]; + uint32 numVertices = batch._params[paramOffset + 2]._uint; + uint32 startVertex = batch._params[paramOffset + 1]._uint; + uint32 startInstance = batch._params[paramOffset + 0]._uint; + + glDrawArraysInstanced(mode, startVertex, numVertices, numInstances); (void) CHECK_GL_ERROR(); } diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 93f3f345f0..f617ecf26f 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -910,6 +910,38 @@ bool Model::addToScene(std::shared_ptr scene, render::PendingChan return somethingAdded; } +bool Model::addToScene(std::shared_ptr scene, render::PendingChanges& pendingChanges, render::Item::Status::Getter& statusGetter) { + if (!_meshGroupsKnown && isLoadedWithTextures()) { + segregateMeshGroups(); + } + + bool somethingAdded = false; + + foreach (auto renderItem, _transparentRenderItems) { + auto item = scene->allocateID(); + auto renderData = MeshPartPayload::Pointer(renderItem); + auto renderPayload = render::PayloadPointer(new MeshPartPayload::Payload(renderData)); + renderPayload->addStatusGetter(statusGetter); + pendingChanges.resetItem(item, renderPayload); + _renderItems.insert(item, renderPayload); + somethingAdded = true; + } + + foreach (auto renderItem, _opaqueRenderItems) { + auto item = scene->allocateID(); + auto renderData = MeshPartPayload::Pointer(renderItem); + auto renderPayload = render::PayloadPointer(new MeshPartPayload::Payload(renderData)); + renderPayload->addStatusGetter(statusGetter); + pendingChanges.resetItem(item, renderPayload); + _renderItems.insert(item, renderPayload); + somethingAdded = true; + } + + _readyWhenAdded = readyToAddToScene(); + + return somethingAdded; +} + void Model::removeFromScene(std::shared_ptr scene, render::PendingChanges& pendingChanges) { foreach (auto item, _renderItems.keys()) { pendingChanges.removeItem(item); diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index 3748403b97..5e440d012d 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -118,6 +118,7 @@ public: bool needsFixupInScene() { return !_readyWhenAdded && readyToAddToScene(); } bool readyToAddToScene(RenderArgs* renderArgs = nullptr) { return !_needsReload && isRenderable() && isActive() && isLoadedWithTextures(); } bool addToScene(std::shared_ptr scene, render::PendingChanges& pendingChanges); + bool addToScene(std::shared_ptr scene, render::PendingChanges& pendingChanges, render::Item::Status::Getter& statusGetter); void removeFromScene(std::shared_ptr scene, render::PendingChanges& pendingChanges); /// Sets the URL of the model to render. diff --git a/libraries/render/src/render/DrawStatus.cpp b/libraries/render/src/render/DrawStatus.cpp index afe9aa3798..ef91efda71 100644 --- a/libraries/render/src/render/DrawStatus.cpp +++ b/libraries/render/src/render/DrawStatus.cpp @@ -42,6 +42,9 @@ const gpu::PipelinePointer& DrawStatus::getDrawItemBoundsPipeline() { gpu::Shader::BindingSet slotBindings; gpu::Shader::makeProgram(*program, slotBindings); + _drawItemBoundPosLoc = program->getUniforms().findLocation("inBoundPos"); + _drawItemBoundDimLoc = program->getUniforms().findLocation("inBoundDim"); + gpu::StatePointer state = gpu::StatePointer(new gpu::State()); state->setDepthTest(true, false, gpu::LESS_EQUAL); @@ -66,6 +69,10 @@ const gpu::PipelinePointer& DrawStatus::getDrawItemStatusPipeline() { gpu::Shader::BindingSet slotBindings; gpu::Shader::makeProgram(*program, slotBindings); + _drawItemStatusPosLoc = program->getUniforms().findLocation("inBoundPos"); + _drawItemStatusDimLoc = program->getUniforms().findLocation("inBoundDim"); + _drawItemStatusValueLoc = program->getUniforms().findLocation("inStatus"); + gpu::StatePointer state = gpu::StatePointer(new gpu::State()); state->setDepthTest(false, false, gpu::LESS_EQUAL); @@ -85,7 +92,49 @@ void DrawStatus::run(const SceneContextPointer& sceneContext, const RenderContex assert(renderContext->args); assert(renderContext->args->_viewFrustum); RenderArgs* args = renderContext->args; + auto& scene = sceneContext->_scene; + // FIrst thing, we collect the bound and the status for all the items we want to render + int nbItems = 0; + { + if (!_itemBounds) { + _itemBounds.reset(new gpu::Buffer()); + } + if (!_itemStatus) { + _itemStatus.reset(new gpu::Buffer()); + } + + _itemBounds->resize((inItems.size() * sizeof(AABox))); + _itemStatus->resize((inItems.size() * sizeof(glm::vec4))); + AABox* itemAABox = reinterpret_cast (_itemBounds->editData()); + glm::vec4* itemStatus = reinterpret_cast (_itemStatus->editData()); + for (auto& item : inItems) { + if (!item.bounds.isInvalid()) { + if (!item.bounds.isNull()) { + (*itemAABox) = item.bounds; + } else { + (*itemAABox).setBox(item.bounds.getCorner(), 0.1f); + } + auto& itemScene = scene->getItem(item.id); + auto& status = itemScene.getStatus(); + if (status) { + status->getValue((*itemStatus)); + } else { + (*itemStatus) = glm::vec4(-1.0f); + } + + nbItems++; + itemAABox++; + itemStatus++; + } + } + } + + if (nbItems == 0) { + return; + } + + // Allright, something to render let's do it gpu::Batch batch; glm::mat4 projMat; @@ -97,46 +146,40 @@ void DrawStatus::run(const SceneContextPointer& sceneContext, const RenderContex } batch.setProjectionTransform(projMat); batch.setViewTransform(viewMat); + batch.setModelTransform(Transform()); - - // batch.setModelTransform(Transform()); - // bind the unit cube geometry +/* if (!_drawItemFormat) { + _drawItemFormat.reset(new gpu::Stream::Format()); + _drawItemFormat->setAttribute(0, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), 0, gpu::Stream::PER_INSTANCE); + _drawItemFormat->setAttribute(1, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), sizeof(glm::vec3), gpu::Stream::PER_INSTANCE); + } +*/ // bind the one gpu::Pipeline we need batch.setPipeline(getDrawItemBoundsPipeline()); - for (auto& item : inItems) { - if (!item.bounds.isInvalid()) { - Transform model; - model.setTranslation(item.bounds.getCorner()); - if (!item.bounds.isNull()) { - model.setScale(item.bounds.getDimensions()); - } + AABox* itemAABox = reinterpret_cast (_itemBounds->editData()); + glm::vec4* itemStatus = reinterpret_cast (_itemStatus->editData()); - batch.setModelTransform(model); - batch.draw(gpu::LINE_STRIP, 13, 0); - } + for (int i = 0; i < nbItems; i++) { + + batch._glUniform3fv(_drawItemBoundPosLoc, 1, (const GLfloat*) (itemAABox + i)); + batch._glUniform3fv(_drawItemBoundDimLoc, 1, ((const GLfloat*) (itemAABox + i)) + 3); + + batch.draw(gpu::LINE_STRIP, 13, 0); } batch.setPipeline(getDrawItemStatusPipeline()); + for (int i = 0; i < nbItems; i++) { + batch._glUniform3fv(_drawItemStatusPosLoc, 1, (const GLfloat*) (itemAABox + i)); + batch._glUniform3fv(_drawItemStatusDimLoc, 1, ((const GLfloat*) (itemAABox + i)) + 3); + batch._glUniform4fv(_drawItemStatusValueLoc, 1, (const GLfloat*) (itemStatus + i)); - for (auto& item : inItems) { - if (!item.bounds.isInvalid()) { - Transform model; - model.setTranslation(item.bounds.getCorner()); - if (!item.bounds.isNull()) { - model.setScale(item.bounds.getDimensions()); - } - - batch.setModelTransform(model); - batch.draw(gpu::TRIANGLE_STRIP, 4, 0); - } + batch.draw(gpu::TRIANGLE_STRIP, 4, 0); } // Before rendering the batch make sure we re in sync with gl state args->_context->syncCache(); renderContext->args->_context->syncCache(); args->_context->render((batch)); - args->_batch = nullptr; - } \ No newline at end of file diff --git a/libraries/render/src/render/DrawStatus.h b/libraries/render/src/render/DrawStatus.h index 079f223ff5..ca4763d33b 100644 --- a/libraries/render/src/render/DrawStatus.h +++ b/libraries/render/src/render/DrawStatus.h @@ -17,8 +17,17 @@ namespace render { class DrawStatus { + int _drawItemBoundPosLoc = -1; + int _drawItemBoundDimLoc = -1; + int _drawItemStatusPosLoc = -1; + int _drawItemStatusDimLoc = -1; + int _drawItemStatusValueLoc = -1; + + gpu::Stream::FormatPointer _drawItemFormat; gpu::PipelinePointer _drawItemBoundsPipeline; gpu::PipelinePointer _drawItemStatusPipeline; + gpu::BufferPointer _itemBounds; + gpu::BufferPointer _itemStatus; public: diff --git a/libraries/render/src/render/Scene.h b/libraries/render/src/render/Scene.h index 444b45800a..75dc92dbdf 100644 --- a/libraries/render/src/render/Scene.h +++ b/libraries/render/src/render/Scene.h @@ -200,13 +200,22 @@ public: // This is Used for monitoring and dynamically adjust the quality class Status { public: - typedef glm::ivec2 Value; + typedef unsigned char Value; typedef std::function Getter; int _firstFrame; std::vector _values; void addGetter(Getter& getter) { _values.push_back(getter); } + void getValue(glm::vec4& value) { + for (unsigned int i = 0; i < value.length(); i++) { + if (i < _values.size()) { + value[i] = _values[i]() / 256; + } else { + value[i] = 0.0f; + } + } + } }; typedef std::shared_ptr StatusPointer; @@ -232,7 +241,7 @@ public: // Status interface is local to the base class const StatusPointer& getStatus() const { return _status; } - void addStatusGetter(Status::Getter& getter) { _status->addGetter(getter); } + void addStatusGetter(Status::Getter& getter) { if (!_status) { _status.reset(new Status());} _status->addGetter(getter); } protected: StatusPointer _status; diff --git a/libraries/render/src/render/drawItemBounds.slv b/libraries/render/src/render/drawItemBounds.slv index e1193a9874..a74d105cf1 100644 --- a/libraries/render/src/render/drawItemBounds.slv +++ b/libraries/render/src/render/drawItemBounds.slv @@ -16,6 +16,9 @@ <$declareStandardTransform()$> +uniform vec3 inBoundPos; +uniform vec3 inBoundDim; + void main(void) { const vec4 UNIT_BOX[13] = vec4[13]( vec4(0.0, 0.0, 0.0, 1.0), @@ -34,6 +37,8 @@ void main(void) { ); vec4 pos = UNIT_BOX[gl_VertexID]; + pos.xyz = inBoundPos + inBoundDim * pos.xyz; + // standard transform TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); diff --git a/libraries/render/src/render/drawItemStatus.slv b/libraries/render/src/render/drawItemStatus.slv index da99d2692e..01f47862bc 100644 --- a/libraries/render/src/render/drawItemStatus.slv +++ b/libraries/render/src/render/drawItemStatus.slv @@ -18,7 +18,9 @@ varying vec4 varColor; -attribute vec4 inStatus; +uniform vec3 inBoundPos; +uniform vec3 inBoundDim; +uniform vec4 inStatus; vec3 paintRainbow(float nv) { float v = nv * 5.f; @@ -51,7 +53,7 @@ void main(void) { varColor = vec4(paintRainbow(inStatus.x), 1.0); - vec4 anchorPoint = vec4(0.5, 0.5, 0.5, 1.0); + vec4 anchorPoint = vec4(inBoundPos, 1.0) + vec4(inBoundDim, 0.0) * vec4(0.5, 0.5, 0.5, 0.0); TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); <$transformModelToClipPos(cam, obj, anchorPoint, anchorPoint)$>