Merge pull request #5041 from ZappoMan/team-teaching-all-entities

TEAM TEACHING - overlays and entities, fix to shrunken avatars
This commit is contained in:
Clément Brisset 2015-06-04 18:00:44 +02:00
commit 7ffe7b31a6
25 changed files with 193 additions and 440 deletions

View file

@ -581,9 +581,11 @@ void Avatar::simulateAttachments(float deltaTime) {
void Avatar::renderAttachments(RenderArgs* args) {
// RenderArgs::RenderMode modelRenderMode = (renderMode == RenderArgs::SHADOW_RENDER_MODE) ?
// RenderArgs::SHADOW_RENDER_MODE : RenderArgs::DEFAULT_RENDER_MODE;
/*
foreach (Model* model, _attachmentModels) {
model->render(args, 1.0f);
}
*/
}
void Avatar::updateJointMappings() {

View file

@ -1580,12 +1580,16 @@ void MyAvatar::renderAttachments(RenderArgs* args) {
QString headJointName = (geometry.headJointIndex == -1) ? QString() : geometry.joints.at(geometry.headJointIndex).name;
// RenderArgs::RenderMode modelRenderMode = (renderMode == RenderArgs::SHADOW_RENDER_MODE) ?
// RenderArgs::SHADOW_RENDER_MODE : RenderArgs::DEFAULT_RENDER_MODE;
// FIX ME - attachments need to be added to scene too...
/*
for (int i = 0; i < _attachmentData.size(); i++) {
const QString& jointName = _attachmentData.at(i).jointName;
if (jointName != headJointName && jointName != "Head") {
_attachmentModels.at(i)->render(args, 1.0f);
}
}
*/
}
//Renders sixense laser pointers for UI selection with controllers

View file

@ -9,6 +9,7 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include <Application.h>
#include <GlowEffect.h>
#include "ModelOverlay.h"
@ -54,11 +55,34 @@ void ModelOverlay::update(float deltatime) {
_isLoaded = _model.isActive();
}
bool ModelOverlay::addToScene(Overlay::Pointer overlay, std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges) {
Base3DOverlay::addToScene(overlay, scene, pendingChanges);
_model.addToScene(scene, pendingChanges);
return true;
}
void ModelOverlay::removeFromScene(Overlay::Pointer overlay, std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges) {
Base3DOverlay::removeFromScene(overlay, scene, pendingChanges);
_model.removeFromScene(scene, pendingChanges);
}
void ModelOverlay::render(RenderArgs* args) {
// check to see if when we added our model to the scene they were ready, if they were not ready, then
// fix them up in the scene
render::ScenePointer scene = Application::getInstance()->getMain3DScene();
render::PendingChanges pendingChanges;
if (_model.needsFixupInScene()) {
_model.removeFromScene(scene, pendingChanges);
_model.addToScene(scene, pendingChanges);
}
scene->enqueuePendingChanges(pendingChanges);
if (!_visible) {
return;
}
/*
if (_model.isActive()) {
if (_model.isRenderable()) {
float glowLevel = getGlowLevel();
@ -72,6 +96,7 @@ void ModelOverlay::render(RenderArgs* args) {
}
}
}
*/
}
void ModelOverlay::setProperties(const QScriptValue &properties) {

View file

@ -32,6 +32,9 @@ public:
virtual ModelOverlay* createClone() const;
virtual bool addToScene(Overlay::Pointer overlay, std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges);
virtual void removeFromScene(Overlay::Pointer overlay, std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges);
private:
Model _model;

View file

@ -228,3 +228,15 @@ float Overlay::updatePulse() {
return _pulse;
}
bool Overlay::addToScene(Overlay::Pointer overlay, std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges) {
auto overlayPayload = new Overlay::Payload(overlay);
auto overlayPayloadPointer = Overlay::PayloadPointer(overlayPayload);
_renderItemID = scene->allocateID();
pendingChanges.resetItem(_renderItemID, overlayPayloadPointer);
return true;
}
void Overlay::removeFromScene(Overlay::Pointer overlay, std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges) {
pendingChanges.removeItem(_renderItemID);
}

View file

@ -48,6 +48,9 @@ public:
virtual void update(float deltatime) {}
virtual void render(RenderArgs* args) = 0;
virtual bool addToScene(Overlay::Pointer overlay, std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges);
virtual void removeFromScene(Overlay::Pointer overlay, std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges);
// getters
virtual bool is3D() const = 0;
bool isLoaded() { return _isLoaded; }
@ -117,5 +120,11 @@ protected:
QScriptEngine* _scriptEngine;
};
namespace render {
template <> const ItemKey payloadGetKey(const Overlay::Pointer& overlay);
template <> const Item::Bound payloadGetBound(const Overlay::Pointer& overlay);
template <> void payloadRender(const Overlay::Pointer& overlay, RenderArgs* args);
}
#endif // hifi_Overlay_h

View file

@ -33,49 +33,6 @@
#include "Text3DOverlay.h"
namespace render {
template <> const ItemKey payloadGetKey(const Overlay::Pointer& overlay) {
if (overlay->is3D() && !static_cast<Base3DOverlay*>(overlay.get())->getDrawOnHUD()) {
if (static_cast<Base3DOverlay*>(overlay.get())->getDrawInFront()) {
return ItemKey::Builder().withTypeShape().withNoDepthSort().build();
} else {
return ItemKey::Builder::opaqueShape();
}
} else {
return ItemKey::Builder().withTypeShape().withViewSpace().build();
}
}
template <> const Item::Bound payloadGetBound(const Overlay::Pointer& overlay) {
if (overlay->is3D()) {
return static_cast<Base3DOverlay*>(overlay.get())->getBounds();
} else {
QRect bounds = static_cast<Overlay2D*>(overlay.get())->getBounds();
return AABox(glm::vec3(bounds.x(), bounds.y(), 0.0f), glm::vec3(bounds.width(), bounds.height(), 0.1f));
}
}
template <> void payloadRender(const Overlay::Pointer& overlay, RenderArgs* args) {
if (args) {
args->_elementsTouched++;
glPushMatrix();
if (overlay->getAnchor() == Overlay::MY_AVATAR) {
MyAvatar* avatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
glm::quat myAvatarRotation = avatar->getOrientation();
glm::vec3 myAvatarPosition = avatar->getPosition();
float angle = glm::degrees(glm::angle(myAvatarRotation));
glm::vec3 axis = glm::axis(myAvatarRotation);
float myAvatarScale = avatar->getScale();
glTranslatef(myAvatarPosition.x, myAvatarPosition.y, myAvatarPosition.z);
glRotatef(angle, axis.x, axis.y, axis.z);
glScalef(myAvatarScale, myAvatarScale, myAvatarScale);
}
overlay->render(args);
glPopMatrix();
}
}
}
Overlays::Overlays() : _nextOverlayID(1) {
}
@ -118,6 +75,7 @@ void Overlays::update(float deltatime) {
void Overlays::cleanupOverlaysToDelete() {
if (!_overlaysToDelete.isEmpty()) {
render::ScenePointer scene = Application::getInstance()->getMain3DScene();
render::PendingChanges pendingChanges;
{
@ -128,13 +86,12 @@ void Overlays::cleanupOverlaysToDelete() {
auto itemID = overlay->getRenderItemID();
if (itemID != render::Item::INVALID_ITEM_ID) {
pendingChanges.removeItem(itemID);
overlay->removeFromScene(overlay, scene, pendingChanges);
}
} while (!_overlaysToDelete.isEmpty());
}
if (pendingChanges._removedItems.size() > 0) {
render::ScenePointer scene = Application::getInstance()->getMain3DScene();
scene->enqueuePendingChanges(pendingChanges);
}
}
@ -216,13 +173,9 @@ unsigned int Overlays::addOverlay(Overlay* overlay) {
_overlaysWorld[thisID] = overlayPointer;
render::ScenePointer scene = Application::getInstance()->getMain3DScene();
auto overlayPayload = new Overlay::Payload(overlayPointer);
auto overlayPayloadPointer = Overlay::PayloadPointer(overlayPayload);
render::ItemID itemID = scene->allocateID();
overlay->setRenderItemID(itemID);
render::PendingChanges pendingChanges;
pendingChanges.resetItem(itemID, overlayPayloadPointer);
overlayPointer->addToScene(overlayPointer, scene, pendingChanges);
scene->enqueuePendingChanges(pendingChanges);
}

View file

@ -0,0 +1,77 @@
//
// OverlaysPayload.cpp
// interface/src/ui/overlays
//
// Copyright 2014 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
//
#include <QScriptValueIterator>
#include <limits>
#include <typeinfo>
#include <Application.h>
#include <avatar/AvatarManager.h>
#include <LODManager.h>
#include <render/Scene.h>
#include "BillboardOverlay.h"
#include "Circle3DOverlay.h"
#include "Cube3DOverlay.h"
#include "ImageOverlay.h"
#include "Line3DOverlay.h"
#include "LocalModelsOverlay.h"
#include "ModelOverlay.h"
#include "Overlays.h"
#include "Rectangle3DOverlay.h"
#include "Sphere3DOverlay.h"
#include "Grid3DOverlay.h"
#include "TextOverlay.h"
#include "Text3DOverlay.h"
namespace render {
template <> const ItemKey payloadGetKey(const Overlay::Pointer& overlay) {
if (overlay->is3D() && !static_cast<Base3DOverlay*>(overlay.get())->getDrawOnHUD()) {
if (static_cast<Base3DOverlay*>(overlay.get())->getDrawInFront()) {
return ItemKey::Builder().withTypeShape().withNoDepthSort().build();
} else {
return ItemKey::Builder::opaqueShape();
}
} else {
return ItemKey::Builder().withTypeShape().withViewSpace().build();
}
}
template <> const Item::Bound payloadGetBound(const Overlay::Pointer& overlay) {
if (overlay->is3D()) {
return static_cast<Base3DOverlay*>(overlay.get())->getBounds();
} else {
QRect bounds = static_cast<Overlay2D*>(overlay.get())->getBounds();
return AABox(glm::vec3(bounds.x(), bounds.y(), 0.0f), glm::vec3(bounds.width(), bounds.height(), 0.1f));
}
}
template <> void payloadRender(const Overlay::Pointer& overlay, RenderArgs* args) {
if (args) {
args->_elementsTouched++;
glPushMatrix();
if (overlay->getAnchor() == Overlay::MY_AVATAR) {
MyAvatar* avatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
glm::quat myAvatarRotation = avatar->getOrientation();
glm::vec3 myAvatarPosition = avatar->getPosition();
float angle = glm::degrees(glm::angle(myAvatarRotation));
glm::vec3 axis = glm::axis(myAvatarRotation);
float myAvatarScale = avatar->getScale();
glTranslatef(myAvatarPosition.x, myAvatarPosition.y, myAvatarPosition.z);
glRotatef(angle, axis.x, axis.y, axis.z);
glScalef(myAvatarScale, myAvatarScale, myAvatarScale);
}
overlay->render(args);
glPopMatrix();
}
}
}

View file

@ -493,45 +493,22 @@ void EntityTreeRenderer::render(RenderArgs* renderArgs) {
if (_tree && !_shuttingDown) {
renderArgs->_renderer = this;
checkPendingAddToScene(renderArgs);
Model::startScene(renderArgs->_renderSide);
ViewFrustum* frustum = (renderArgs->_renderMode == RenderArgs::SHADOW_RENDER_MODE) ?
_viewState->getShadowViewFrustum() : _viewState->getCurrentViewFrustum();
// Setup batch transform matrices
gpu::Batch batch; // FIX ME - this is very suspicious!
glm::mat4 projMat;
Transform viewMat;
frustum->evalProjectionMatrix(projMat);
frustum->evalViewTransform(viewMat);
batch.setProjectionTransform(projMat);
batch.setViewTransform(viewMat);
renderArgs->_batch = &batch; // FIX ME - this is very suspicious!
_tree->lockForRead();
// Whenever you're in an intersection between zones, we will always choose the smallest zone.
_bestZone = NULL; // NOTE: Is this what we want?
_bestZoneVolume = std::numeric_limits<float>::max();
// FIX ME: right now the renderOperation does the following:
// 1) determining the best zone (not really rendering)
// 2) render the debug cell details
// we should clean this up
_tree->recurseTreeWithOperation(renderOperation, renderArgs);
applyZonePropertiesToScene(_bestZone);
// we must call endScene while we still have the tree locked so that no one deletes a model
// on us while rendering the scene
Model::endScene(renderArgs);
_tree->unlock();
// FIX ME - this is very suspicious!
// glPushMatrix();
// renderArgs->_context->render(batch);
// glPopMatrix();
renderArgs->_batch = nullptr;
// stats...
_meshesConsidered = renderArgs->_meshesConsidered;
_meshesRendered = renderArgs->_meshesRendered;
@ -715,39 +692,6 @@ void EntityTreeRenderer::renderElement(OctreeElement* element, RenderArgs* args)
}
}
}
// hack for models and other entities that don't yet play well with others. :(
if (!entityItem->canRenderInScene()) {
// render entityItem
AABox entityBox = entityItem->getAABox();
// TODO: some entity types (like lights) might want to be rendered even
// when they are outside of the view frustum...
float distance = args->_viewFrustum->distanceToCamera(entityBox.calcCenter());
bool outOfView = args->_viewFrustum->boxInFrustum(entityBox) == ViewFrustum::OUTSIDE;
if (!outOfView) {
bool bigEnoughToRender = _viewState->shouldRenderMesh(entityBox.getLargestDimension(), distance);
if (bigEnoughToRender) {
renderProxies(entityItem, args);
Glower* glower = NULL;
if (entityItem->getGlowLevel() > 0.0f) {
glower = new Glower(args, entityItem->getGlowLevel());
}
entityItem->render(args);
args->_itemsRendered++;
if (glower) {
delete glower;
}
} else {
args->_itemsTooSmall++;
}
} else {
args->_itemsOutOfView++;
}
}
}
}
}
@ -1093,34 +1037,14 @@ void EntityTreeRenderer::addingEntity(const EntityItemID& entityID) {
void EntityTreeRenderer::addEntityToScene(EntityItemPointer entity) {
// here's where we add the entity payload to the scene
if (entity && entity->canRenderInScene()) {
if (entity->readyToAddToScene()) {
render::PendingChanges pendingChanges;
auto scene = _viewState->getMain3DScene();
if (entity->addToScene(entity, scene, pendingChanges)) {
_entitiesInScene.insert(entity);
}
scene->enqueuePendingChanges(pendingChanges);
} else {
if (!_pendingAddToScene.contains(entity)) {
_pendingAddToScene << entity;
}
}
render::PendingChanges pendingChanges;
auto scene = _viewState->getMain3DScene();
if (entity->addToScene(entity, scene, pendingChanges)) {
_entitiesInScene.insert(entity);
}
scene->enqueuePendingChanges(pendingChanges);
}
void EntityTreeRenderer::checkPendingAddToScene(RenderArgs* renderArgs) {
QSet<EntityItemPointer> addedToScene;
foreach (auto entity, _pendingAddToScene) {
if (entity->readyToAddToScene(renderArgs)) {
addEntityToScene(entity);
addedToScene << entity;
}
}
foreach (auto addedEntity, addedToScene) {
_pendingAddToScene.remove(addedEntity);
}
}
void EntityTreeRenderer::entitySciptChanging(const EntityItemID& entityID) {
if (_tree && !_shuttingDown) {

View file

@ -123,9 +123,7 @@ protected:
virtual Octree* createTree() { return new EntityTree(true); }
private:
void checkPendingAddToScene(RenderArgs* renderArgs);
void addEntityToScene(EntityItemPointer entity);
QSet<EntityItemPointer> _pendingAddToScene;
void applyZonePropertiesToScene(std::shared_ptr<ZoneEntityItem> zone);
void renderElementProxy(EntityTreeElement* entityTreeElement, RenderArgs* args);

View file

@ -32,9 +32,7 @@ namespace render {
if (args) {
args->_elementsTouched++;
if (payload && payload->entity) {
if (payload->entity->getType() != EntityTypes::Model) {
payload->entity->render(args);
}
payload->entity->render(args);
}
}
}

View file

@ -56,7 +56,6 @@ private:
#define SIMPLE_RENDERABLE() \
public: \
virtual bool canRenderInScene() { return true; } \
virtual bool addToScene(EntityItemPointer self, std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges) { return _renderHelper.addToScene(self, scene, pendingChanges); } \
virtual void removeFromScene(EntityItemPointer self, std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges) { _renderHelper.removeFromScene(self, scene, pendingChanges); } \
private: \

View file

@ -13,6 +13,7 @@
#define hifi_RenderableLightEntityItem_h
#include <LightEntityItem.h>
#include "RenderableEntityItem.h"
class RenderableLightEntityItem : public LightEntityItem {
public:
@ -22,12 +23,13 @@ public:
LightEntityItem(entityItemID, properties)
{ }
virtual bool canRenderInScene() { return false; } // we don't yet play well with others
virtual void render(RenderArgs* args);
virtual bool supportsDetailedRayIntersection() const { return true; }
virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face,
void** intersectedObject, bool precisionPicking) const;
SIMPLE_RENDERABLE();
};

View file

@ -28,7 +28,7 @@ public:
virtual void render(RenderArgs* args);
SIMPLE_RENDERABLE()
SIMPLE_RENDERABLE();
protected:
void updateGeometry();

View file

@ -15,6 +15,7 @@
#include <QJsonDocument>
#include <AbstractViewStateInterface.h>
#include <DeferredLightingEffect.h>
#include <Model.h>
#include <PerfStat.h>
@ -210,6 +211,19 @@ void RenderableModelEntityItem::render(RenderArgs* args) {
}
if (hasModel()) {
if (_model) {
// check to see if when we added our models to the scene they were ready, if they were not ready, then
// fix them up in the scene
render::ScenePointer scene = AbstractViewStateInterface::instance()->getMain3DScene();
render::PendingChanges pendingChanges;
if (_model->needsFixupInScene()) {
_model->removeFromScene(scene, pendingChanges);
_model->addToScene(scene, pendingChanges);
}
scene->enqueuePendingChanges(pendingChanges);
}
remapTextures();
{
float alpha = getLocalRenderAlpha();

View file

@ -43,7 +43,6 @@ public:
virtual void somethingChangedNotification() { _needsInitialSimulation = true; }
virtual bool canRenderInScene() { return true; }
virtual bool readyToAddToScene(RenderArgs* renderArgs = nullptr);
virtual bool addToScene(EntityItemPointer self, std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges);
virtual void removeFromScene(EntityItemPointer self, std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges);

View file

@ -23,7 +23,7 @@ public:
void updateQuads(RenderArgs* args, bool textured);
SIMPLE_RENDERABLE()
SIMPLE_RENDERABLE();
protected:

View file

@ -16,6 +16,7 @@
#include "PolyVoxEntityItem.h"
#include "RenderableDebugableEntityItem.h"
#include "RenderableEntityItem.h"
class RenderablePolyVoxEntityItem : public PolyVoxEntityItem {
public:
@ -70,6 +71,8 @@ public:
virtual void setAll(uint8_t toValue);
virtual void setVoxelInVolume(glm::vec3 position, uint8_t toValue);
SIMPLE_RENDERABLE();
private:
// The PolyVoxEntityItem class has _voxelData which contains dimensions and compressed voxel data. The dimensions

View file

@ -26,7 +26,7 @@ public:
virtual void render(RenderArgs* args);
SIMPLE_RENDERABLE()
SIMPLE_RENDERABLE();
};

View file

@ -15,6 +15,8 @@
#include <TextEntityItem.h>
#include <TextRenderer3D.h>
#include "RenderableEntityItem.h"
const int FIXED_FONT_POINT_SIZE = 40;
class RenderableTextEntityItem : public TextEntityItem {
@ -27,7 +29,8 @@ public:
~RenderableTextEntityItem() { delete _textRenderer; }
virtual void render(RenderArgs* args);
virtual bool canRenderInScene() { return false; } // we don't yet play well with others
SIMPLE_RENDERABLE();
private:
TextRenderer3D* _textRenderer = TextRenderer3D::getInstance(SANS_FONT_FAMILY, FIXED_FONT_POINT_SIZE / 2.0f);

View file

@ -13,6 +13,8 @@
#include <WebEntityItem.h>
#include "RenderableEntityItem.h"
class OffscreenQmlSurface;
class RenderableWebEntityItem : public WebEntityItem {
@ -24,7 +26,8 @@ public:
virtual void render(RenderArgs* args);
virtual void setSourceUrl(const QString& value);
virtual bool canRenderInScene() { return false; } // we don't yet play well with others
SIMPLE_RENDERABLE();
private:
OffscreenQmlSurface* _webSurface{ nullptr };

View file

@ -102,7 +102,8 @@ void RenderableZoneEntityItem::render(RenderArgs* args) {
updateGeometry();
if (_model && _model->isActive()) {
_model->renderInScene(getLocalRenderAlpha(), args);
// FIX ME: this is no longer available... we need to switch to payloads
//_model->renderInScene(getLocalRenderAlpha(), args);
}
break;
}

View file

@ -157,8 +157,6 @@ public:
EntityPropertyFlags& propertyFlags, bool overwriteLocalData)
{ return 0; }
virtual bool canRenderInScene() { return false; } // does your entity property render using Render Items and Payloads
virtual bool readyToAddToScene(RenderArgs* renderArgs = nullptr) { return true; } // we assume you're ready to add
virtual bool addToScene(EntityItemPointer self, std::shared_ptr<render::Scene> scene,
render::PendingChanges& pendingChanges) { return false; } // by default entity items don't add to scene
virtual void removeFromScene(EntityItemPointer self, std::shared_ptr<render::Scene> scene,

View file

@ -925,6 +925,7 @@ void Model::removeFromScene(std::shared_ptr<render::Scene> scene, render::Pendin
}
bool Model::render(RenderArgs* renderArgs, float alpha) {
return true; //
PROFILE_RANGE(__FUNCTION__);
// render the attachments
@ -1994,15 +1995,6 @@ void Model::deleteGeometry() {
_blendedBlendshapeCoefficients.clear();
}
// Scene rendering support
QVector<Model*> Model::_modelsInScene;
gpu::Batch Model::_sceneRenderBatch;
void Model::startScene(RenderArgs::RenderSide renderSide) {
if (renderSide != RenderArgs::STEREO_RIGHT) {
_modelsInScene.clear();
}
}
void Model::setupBatchTransform(gpu::Batch& batch, RenderArgs* args) {
// Capture the view matrix once for the rendering of this model
@ -2019,231 +2011,6 @@ void Model::setupBatchTransform(gpu::Batch& batch, RenderArgs* args) {
batch.setViewTransform(_transforms[0]);
}
void Model::endScene(RenderArgs* args) {
// Now that we migrated everything to the new RENDER/SCENE no more work to do!
return;
PROFILE_RANGE(__FUNCTION__);
#if (GPU_TRANSFORM_PROFILE == GPU_LEGACY)
// with legacy transform profile, we still to protect that transform stack...
glPushMatrix();
#endif
auto mode = args->_renderMode;
RenderArgs::RenderSide renderSide = RenderArgs::MONO;
if (args) {
renderSide = args->_renderSide;
}
gpu::GLBackend backend;
backend.syncCache(); // force sync with gl state here
if (args) {
glm::mat4 proj;
// If for easier debug depending on the pass
if (mode == RenderArgs::SHADOW_RENDER_MODE) {
args->_viewFrustum->evalProjectionMatrix(proj);
} else {
args->_viewFrustum->evalProjectionMatrix(proj);
}
gpu::Batch batch;
batch.setProjectionTransform(proj);
backend.render(batch);
}
// Do the rendering batch creation for mono or left eye, not for right eye
if (renderSide != RenderArgs::STEREO_RIGHT) {
// Let's introduce a gpu::Batch to capture all the calls to the graphics api
_sceneRenderBatch.clear();
gpu::Batch& batch = _sceneRenderBatch;
/*DependencyManager::get<TextureCache>()->setPrimaryDrawBuffers(
mode == RenderArgs::DEFAULT_RENDER_MODE || mode == RenderArgs::DIFFUSE_RENDER_MODE,
mode == RenderArgs::DEFAULT_RENDER_MODE || mode == RenderArgs::NORMAL_RENDER_MODE,
mode == RenderArgs::DEFAULT_RENDER_MODE);
*/
/* if (mode != RenderArgs::SHADOW_RENDER_MODE) */{
GLenum buffers[3];
int bufferCount = 0;
// if (mode == RenderArgs::DEFAULT_RENDER_MODE || mode == RenderArgs::DIFFUSE_RENDER_MODE) {
if (mode != RenderArgs::SHADOW_RENDER_MODE) {
buffers[bufferCount++] = GL_COLOR_ATTACHMENT0;
}
//if (mode == RenderArgs::DEFAULT_RENDER_MODE || mode == RenderArgs::NORMAL_RENDER_MODE) {
if (mode != RenderArgs::SHADOW_RENDER_MODE) {
buffers[bufferCount++] = GL_COLOR_ATTACHMENT1;
}
// if (mode == RenderArgs::DEFAULT_RENDER_MODE) {
if (mode != RenderArgs::SHADOW_RENDER_MODE) {
buffers[bufferCount++] = GL_COLOR_ATTACHMENT2;
}
GLBATCH(glDrawBuffers)(bufferCount, buffers);
// batch.setFramebuffer(DependencyManager::get<TextureCache>()->getPrimaryOpaqueFramebuffer());
}
const float DEFAULT_ALPHA_THRESHOLD = 0.5f;
int opaqueMeshPartsRendered = 0;
// now, for each model in the scene, render the mesh portions
opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, false, false, false, args);
opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, false, true, false, args);
opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, true, false, false, args);
opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, true, true, false, args);
opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, false, false, false, args);
opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, false, true, false, args);
opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, true, false, false, args);
opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, true, true, false, args);
opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, false, false, false, args);
opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, true, false, false, args);
opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, false, false, false, args);
opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, true, false, false, args);
opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, false, false, true, args);
// render translucent meshes afterwards
{
GLenum buffers[2];
int bufferCount = 0;
buffers[bufferCount++] = GL_COLOR_ATTACHMENT1;
buffers[bufferCount++] = GL_COLOR_ATTACHMENT2;
GLBATCH(glDrawBuffers)(bufferCount, buffers);
}
int translucentParts = 0;
const float MOSTLY_OPAQUE_THRESHOLD = 0.75f;
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, false, false, false, args);
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, false, true, false, args);
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, true, false, false, args);
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, true, true, false, args);
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, false, false, false, args);
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, false, true, false, args);
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, true, false, false, args);
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, true, true, false, args);
{
GLenum buffers[1];
int bufferCount = 0;
buffers[bufferCount++] = GL_COLOR_ATTACHMENT0;
GLBATCH(glDrawBuffers)(bufferCount, buffers);
// batch.setFramebuffer(DependencyManager::get<TextureCache>()->getPrimaryTransparentFramebuffer());
}
// if (mode == RenderArgs::DEFAULT_RENDER_MODE || mode == RenderArgs::DIFFUSE_RENDER_MODE) {
if (mode != RenderArgs::SHADOW_RENDER_MODE) {
// batch.setFramebuffer(DependencyManager::get<TextureCache>()->getPrimaryTransparentFramebuffer());
const float MOSTLY_TRANSPARENT_THRESHOLD = 0.0f;
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, false, false, false, args);
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, false, true, false, args);
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, true, false, false, args);
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, true, true, false, args);
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, false, false, false, args);
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, false, true, false, args);
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, true, false, false, args);
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, true, true, false, args);
// batch.setFramebuffer(DependencyManager::get<TextureCache>()->getPrimaryOpaqueFramebuffer());
}
GLBATCH(glDepthMask)(true);
GLBATCH(glDepthFunc)(GL_LESS);
GLBATCH(glDisable)(GL_CULL_FACE);
if (mode == RenderArgs::SHADOW_RENDER_MODE) {
GLBATCH(glCullFace)(GL_BACK);
}
GLBATCH(glActiveTexture)(GL_TEXTURE0 + 1);
GLBATCH(glBindTexture)(GL_TEXTURE_2D, 0);
GLBATCH(glActiveTexture)(GL_TEXTURE0 + 2);
GLBATCH(glBindTexture)(GL_TEXTURE_2D, 0);
GLBATCH(glActiveTexture)(GL_TEXTURE0 + 3);
GLBATCH(glBindTexture)(GL_TEXTURE_2D, 0);
GLBATCH(glActiveTexture)(GL_TEXTURE0);
GLBATCH(glBindTexture)(GL_TEXTURE_2D, 0);
// deactivate vertex arrays after drawing
GLBATCH(glDisableClientState)(GL_NORMAL_ARRAY);
GLBATCH(glDisableClientState)(GL_VERTEX_ARRAY);
GLBATCH(glDisableClientState)(GL_TEXTURE_COORD_ARRAY);
GLBATCH(glDisableClientState)(GL_COLOR_ARRAY);
GLBATCH(glDisableVertexAttribArray)(gpu::Stream::TANGENT);
GLBATCH(glDisableVertexAttribArray)(gpu::Stream::SKIN_CLUSTER_INDEX);
GLBATCH(glDisableVertexAttribArray)(gpu::Stream::SKIN_CLUSTER_WEIGHT);
// bind with 0 to switch back to normal operation
GLBATCH(glBindBuffer)(GL_ARRAY_BUFFER, 0);
GLBATCH(glBindBuffer)(GL_ELEMENT_ARRAY_BUFFER, 0);
GLBATCH(glBindTexture)(GL_TEXTURE_2D, 0);
// Back to no program
GLBATCH(glUseProgram)(0);
if (args) {
args->_translucentMeshPartsRendered = translucentParts;
args->_opaqueMeshPartsRendered = opaqueMeshPartsRendered;
}
}
// Render!
{
PROFILE_RANGE("render Batch");
backend.render(_sceneRenderBatch);
}
#if (GPU_TRANSFORM_PROFILE == GPU_LEGACY)
// with legacy transform profile, we still to protect that transform stack...
glPopMatrix();
#endif
// restore all the default material settings
_viewState->setupWorldLight();
}
bool Model::renderInScene(float alpha, RenderArgs* args) {
// render the attachments
foreach (Model* attachment, _attachments) {
attachment->renderInScene(alpha);
}
if (_meshStates.isEmpty()) {
return false;
}
if (args->_debugFlags == RenderArgs::RENDER_DEBUG_HULLS && _renderCollisionHull == false) {
// turning collision hull rendering on
_renderCollisionHull = true;
_nextGeometry = _collisionGeometry;
_saveNonCollisionGeometry = _geometry;
updateGeometry();
simulate(0.0, true);
} else if (args->_debugFlags != RenderArgs::RENDER_DEBUG_HULLS && _renderCollisionHull == true) {
// turning collision hull rendering off
_renderCollisionHull = false;
_nextGeometry = _saveNonCollisionGeometry;
_saveNonCollisionGeometry.clear();
updateGeometry();
simulate(0.0, true);
}
renderSetup(args);
_modelsInScene.push_back(this);
return true;
}
AABox Model::getPartBounds(int meshIndex, int partIndex) {
if (!_calculatedMeshPartBoxesValid) {
@ -2329,21 +2096,17 @@ void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, bool tran
return; // FIXME!
}
if (state.clusterMatrices.size() > 1) {
if (isSkinned) {
GLBATCH(glUniformMatrix4fv)(locations->clusterMatrices, state.clusterMatrices.size(), false,
(const float*)state.clusterMatrices.constData());
// batch.setModelTransform(Transform());
_transforms[0].setTranslation(_translation);
_transforms[0] = Transform();
_transforms[0].preTranslate(_translation);
} else {
_transforms[0] = Transform(state.clusterMatrices[0]);
_transforms[0].preTranslate(_translation);
//batch.setModelTransform(Transform(state.clusterMatrices[0]));
}
batch.setModelTransform(_transforms[0]);
if (mesh.blendshapes.isEmpty()) {
batch.setInputFormat(networkMesh._vertexFormat);
batch.setInputStream(0, *networkMesh._vertexStream);
@ -2588,34 +2351,6 @@ void Model::pickPrograms(gpu::Batch& batch, RenderMode mode, bool translucent, f
}
}
int Model::renderMeshesForModelsInScene(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold,
bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, bool isWireframe, RenderArgs* args) {
PROFILE_RANGE(__FUNCTION__);
int meshPartsRendered = 0;
bool pickProgramsNeeded = true;
Locations* locations = nullptr;
foreach(Model* model, _modelsInScene) {
QVector<int>* whichList = model->pickMeshList(translucent, alphaThreshold, hasLightmap, hasTangents, hasSpecular, isSkinned, isWireframe);
if (whichList) {
QVector<int>& list = *whichList;
if (list.size() > 0) {
if (pickProgramsNeeded) {
pickPrograms(batch, mode, translucent, alphaThreshold, hasLightmap, hasTangents, hasSpecular, isSkinned, isWireframe, args, locations);
pickProgramsNeeded = false;
}
model->setupBatchTransform(batch, args);
meshPartsRendered += model->renderMeshesFromList(list, batch, mode, translucent, alphaThreshold, args, locations);
}
}
}
return meshPartsRendered;
}
int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold,
bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, bool isWireframe, RenderArgs* args,
bool forceRenderSomeMeshes) {

View file

@ -114,14 +114,8 @@ public:
void reset();
virtual void simulate(float deltaTime, bool fullUpdate = true);
bool render(RenderArgs* renderArgs, float alpha = 1.0f);
void renderSetup(RenderArgs* args);
// Scene rendering support
static void startScene(RenderArgs::RenderSide renderSide);
bool renderInScene(float alpha = 1.0f, RenderArgs* args = NULL);
static void endScene(RenderArgs* args);
// new Scene/Engine rendering support
bool needsFixupInScene() { return !_readyWhenAdded && readyToAddToScene(); }
bool readyToAddToScene(RenderArgs* renderArgs = nullptr) { return isRenderable() && isActive() && isLoadedWithTextures(); }
@ -393,13 +387,6 @@ private:
void renderDebugMeshBoxes();
int _debugMeshBoxesID = GeometryCache::UNKNOWN_ID;
// Scene rendering support
static QVector<Model*> _modelsInScene;
static gpu::Batch _sceneRenderBatch;
static void endSceneSimple(RenderArgs::RenderMode mode = RenderArgs::DEFAULT_RENDER_MODE, RenderArgs* args = NULL);
static void endSceneSplitPass(RenderArgs::RenderMode mode = RenderArgs::DEFAULT_RENDER_MODE, RenderArgs* args = NULL);
// helper functions used by render() or renderInScene()
bool renderCore(RenderArgs* args, float alpha);
int renderMeshes(gpu::Batch& batch, RenderArgs::RenderMode mode, bool translucent, float alphaThreshold,
@ -417,10 +404,6 @@ private:
bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, bool isWireframe, RenderArgs* args,
Locations*& locations);
static int renderMeshesForModelsInScene(gpu::Batch& batch, RenderArgs::RenderMode mode, bool translucent, float alphaThreshold,
bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, bool isWireframe, RenderArgs* args);
static AbstractViewStateInterface* _viewState;
class RenderKey {
@ -547,6 +530,14 @@ private:
QSet<std::shared_ptr<OpaqueMeshPart>> _opaqueRenderItems;
QSet<render::ItemID> _renderItems;
bool _readyWhenAdded = false;
private:
// FIX ME - We want to get rid of this interface for rendering...
// right now the only remaining user are Avatar attachments.
// that usage has been temporarily disabled...
bool render(RenderArgs* renderArgs, float alpha = 1.0f);
};
Q_DECLARE_METATYPE(QPointer<Model>)