Merge branch 'master' into 5783-Restarting-Interface-allows-you-to-have-Avatar-Scale-Too-Big

This commit is contained in:
NeetBhagat 2017-07-11 19:23:46 +05:30
commit 1a47383d4f
56 changed files with 1115 additions and 268 deletions

View file

@ -85,7 +85,22 @@ void AvatarMixer::handleReplicatedPacket(QSharedPointer<ReceivedMessage> message
auto nodeList = DependencyManager::get<NodeList>(); auto nodeList = DependencyManager::get<NodeList>();
auto nodeID = QUuid::fromRfc4122(message->peek(NUM_BYTES_RFC4122_UUID)); auto nodeID = QUuid::fromRfc4122(message->peek(NUM_BYTES_RFC4122_UUID));
auto replicatedNode = addOrUpdateReplicatedNode(nodeID, message->getSenderSockAddr()); SharedNodePointer replicatedNode;
if (message->getType() == PacketType::ReplicatedKillAvatar) {
// this is a kill packet, which we should only process if we already have the node in our list
// since it of course does not make sense to add a node just to remove it an instant later
replicatedNode = nodeList->nodeWithUUID(nodeID);
if (!replicatedNode) {
return;
}
} else {
replicatedNode = addOrUpdateReplicatedNode(nodeID, message->getSenderSockAddr());
}
// we better have a node to work with at this point
assert(replicatedNode);
if (message->getType() == PacketType::ReplicatedAvatarIdentity) { if (message->getType() == PacketType::ReplicatedAvatarIdentity) {
handleAvatarIdentityPacket(message, replicatedNode); handleAvatarIdentityPacket(message, replicatedNode);

View file

@ -99,7 +99,13 @@ StackView {
height: parent.height height: parent.height
MouseArea { MouseArea {
anchors.fill: parent anchors {
top: parent.top
left: parent.left
right: parent.right
bottom: keyboard.top
}
propagateComposedEvents: true propagateComposedEvents: true
onPressed: { onPressed: {
parent.forceActiveFocus(); parent.forceActiveFocus();

View file

@ -112,10 +112,7 @@
#include <plugins/InputConfiguration.h> #include <plugins/InputConfiguration.h>
#include <RecordingScriptingInterface.h> #include <RecordingScriptingInterface.h>
#include <RenderableWebEntityItem.h> #include <RenderableWebEntityItem.h>
#include <RenderShadowTask.h> #include <UpdateSceneTask.h>
#include <render/RenderFetchCullSortTask.h>
#include <RenderDeferredTask.h>
#include <RenderForwardTask.h>
#include <RenderViewTask.h> #include <RenderViewTask.h>
#include <SecondaryCamera.h> #include <SecondaryCamera.h>
#include <ResourceCache.h> #include <ResourceCache.h>
@ -1973,6 +1970,7 @@ void Application::initializeGL() {
render::CullFunctor cullFunctor = LODManager::shouldRender; render::CullFunctor cullFunctor = LODManager::shouldRender;
static const QString RENDER_FORWARD = "HIFI_RENDER_FORWARD"; static const QString RENDER_FORWARD = "HIFI_RENDER_FORWARD";
bool isDeferred = !QProcessEnvironment::systemEnvironment().contains(RENDER_FORWARD); bool isDeferred = !QProcessEnvironment::systemEnvironment().contains(RENDER_FORWARD);
_renderEngine->addJob<UpdateSceneTask>("UpdateScene");
_renderEngine->addJob<SecondaryCameraRenderTask>("SecondaryCameraFrame", cullFunctor); _renderEngine->addJob<SecondaryCameraRenderTask>("SecondaryCameraFrame", cullFunctor);
_renderEngine->addJob<RenderViewTask>("RenderMainView", cullFunctor, isDeferred); _renderEngine->addJob<RenderViewTask>("RenderMainView", cullFunctor, isDeferred);
_renderEngine->load(); _renderEngine->load();
@ -5312,7 +5310,7 @@ namespace render {
auto& batch = *args->_batch; auto& batch = *args->_batch;
DependencyManager::get<GeometryCache>()->bindSimpleProgram(batch); DependencyManager::get<GeometryCache>()->bindSimpleProgram(batch);
renderWorldBox(batch); renderWorldBox(args, batch);
} }
} }
} }
@ -5375,10 +5373,7 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se
} }
{ {
PerformanceTimer perfTimer("SceneProcessTransaction");
_main3DScene->enqueueTransaction(transaction); _main3DScene->enqueueTransaction(transaction);
_main3DScene->processTransactionQueue();
} }
// For now every frame pass the renderContext // For now every frame pass the renderContext

View file

@ -34,7 +34,7 @@
using namespace std; using namespace std;
void renderWorldBox(gpu::Batch& batch) { void renderWorldBox(RenderArgs* args, gpu::Batch& batch) {
auto geometryCache = DependencyManager::get<GeometryCache>(); auto geometryCache = DependencyManager::get<GeometryCache>();
// Show center of world // Show center of world
@ -115,7 +115,7 @@ void renderWorldBox(gpu::Batch& batch) {
geometryIds[17]); geometryIds[17]);
geometryCache->renderWireCubeInstance(batch, GREY4); geometryCache->renderWireCubeInstance(args, batch, GREY4);
// Draw meter markers along the 3 axis to help with measuring things // Draw meter markers along the 3 axis to help with measuring things
const float MARKER_DISTANCE = 1.0f; const float MARKER_DISTANCE = 1.0f;
@ -123,23 +123,23 @@ void renderWorldBox(gpu::Batch& batch) {
transform = Transform().setScale(MARKER_RADIUS); transform = Transform().setScale(MARKER_RADIUS);
batch.setModelTransform(transform); batch.setModelTransform(transform);
geometryCache->renderSolidSphereInstance(batch, RED); geometryCache->renderSolidSphereInstance(args, batch, RED);
transform = Transform().setTranslation(glm::vec3(MARKER_DISTANCE, 0.0f, 0.0f)).setScale(MARKER_RADIUS); transform = Transform().setTranslation(glm::vec3(MARKER_DISTANCE, 0.0f, 0.0f)).setScale(MARKER_RADIUS);
batch.setModelTransform(transform); batch.setModelTransform(transform);
geometryCache->renderSolidSphereInstance(batch, RED); geometryCache->renderSolidSphereInstance(args, batch, RED);
transform = Transform().setTranslation(glm::vec3(0.0f, MARKER_DISTANCE, 0.0f)).setScale(MARKER_RADIUS); transform = Transform().setTranslation(glm::vec3(0.0f, MARKER_DISTANCE, 0.0f)).setScale(MARKER_RADIUS);
batch.setModelTransform(transform); batch.setModelTransform(transform);
geometryCache->renderSolidSphereInstance(batch, GREEN); geometryCache->renderSolidSphereInstance(args, batch, GREEN);
transform = Transform().setTranslation(glm::vec3(0.0f, 0.0f, MARKER_DISTANCE)).setScale(MARKER_RADIUS); transform = Transform().setTranslation(glm::vec3(0.0f, 0.0f, MARKER_DISTANCE)).setScale(MARKER_RADIUS);
batch.setModelTransform(transform); batch.setModelTransform(transform);
geometryCache->renderSolidSphereInstance(batch, BLUE); geometryCache->renderSolidSphereInstance(args, batch, BLUE);
transform = Transform().setTranslation(glm::vec3(MARKER_DISTANCE, 0.0f, MARKER_DISTANCE)).setScale(MARKER_RADIUS); transform = Transform().setTranslation(glm::vec3(MARKER_DISTANCE, 0.0f, MARKER_DISTANCE)).setScale(MARKER_RADIUS);
batch.setModelTransform(transform); batch.setModelTransform(transform);
geometryCache->renderSolidSphereInstance(batch, GREY); geometryCache->renderSolidSphereInstance(args, batch, GREY);
} }
// Do some basic timing tests and report the results // Do some basic timing tests and report the results

View file

@ -16,8 +16,9 @@
#include <glm/gtc/quaternion.hpp> #include <glm/gtc/quaternion.hpp>
#include <gpu/Batch.h> #include <gpu/Batch.h>
#include <render/Forward.h>
void renderWorldBox(gpu::Batch& batch); void renderWorldBox(RenderArgs* args, gpu::Batch& batch);
void runTimingTests(); void runTimingTests();
void runUnitTests(); void runUnitTests();

View file

@ -1353,6 +1353,7 @@ void MyAvatar::setSkeletonModelURL(const QUrl& skeletonModelURL) {
Avatar::setSkeletonModelURL(skeletonModelURL); Avatar::setSkeletonModelURL(skeletonModelURL);
_skeletonModel->setVisibleInScene(true, qApp->getMain3DScene()); _skeletonModel->setVisibleInScene(true, qApp->getMain3DScene());
_headBoneSet.clear(); _headBoneSet.clear();
emit skeletonChanged();
} }

View file

@ -606,6 +606,7 @@ signals:
void onLoadComplete(); void onLoadComplete();
void wentAway(); void wentAway();
void wentActive(); void wentActive();
void skeletonChanged();
private: private:

View file

@ -80,8 +80,8 @@ void Circle3DOverlay::render(RenderArgs* args) {
Q_ASSERT(args->_batch); Q_ASSERT(args->_batch);
auto& batch = *args->_batch; auto& batch = *args->_batch;
if (args->_pipeline) { if (args->_shapePipeline) {
batch.setPipeline(args->_pipeline->pipeline); batch.setPipeline(args->_shapePipeline->pipeline);
} }
// FIXME: THe line width of _lineWidth is not supported anymore, we ll need a workaround // FIXME: THe line width of _lineWidth is not supported anymore, we ll need a workaround

View file

@ -65,15 +65,15 @@ void Cube3DOverlay::render(RenderArgs* args) {
transform.setTranslation(position); transform.setTranslation(position);
transform.setRotation(rotation); transform.setRotation(rotation);
auto geometryCache = DependencyManager::get<GeometryCache>(); auto geometryCache = DependencyManager::get<GeometryCache>();
auto pipeline = args->_pipeline; auto shapePipeline = args->_shapePipeline;
if (!pipeline) { if (!shapePipeline) {
pipeline = _isSolid ? geometryCache->getOpaqueShapePipeline() : geometryCache->getWireShapePipeline(); shapePipeline = _isSolid ? geometryCache->getOpaqueShapePipeline() : geometryCache->getWireShapePipeline();
} }
if (_isSolid) { if (_isSolid) {
transform.setScale(dimensions); transform.setScale(dimensions);
batch->setModelTransform(transform); batch->setModelTransform(transform);
geometryCache->renderSolidCubeInstance(*batch, cubeColor, pipeline); geometryCache->renderSolidCubeInstance(args, *batch, cubeColor, shapePipeline);
} else { } else {
geometryCache->bindSimpleProgram(*batch, false, false, false, true, true); geometryCache->bindSimpleProgram(*batch, false, false, false, true, true);
if (getIsDashedLine()) { if (getIsDashedLine()) {
@ -109,7 +109,7 @@ void Cube3DOverlay::render(RenderArgs* args) {
} else { } else {
transform.setScale(dimensions); transform.setScale(dimensions);
batch->setModelTransform(transform); batch->setModelTransform(transform);
geometryCache->renderWireCubeInstance(*batch, cubeColor, pipeline); geometryCache->renderWireCubeInstance(args, *batch, cubeColor, shapePipeline);
} }
} }
} }

View file

@ -45,17 +45,17 @@ void Shape3DOverlay::render(RenderArgs* args) {
transform.setTranslation(position); transform.setTranslation(position);
transform.setRotation(rotation); transform.setRotation(rotation);
auto geometryCache = DependencyManager::get<GeometryCache>(); auto geometryCache = DependencyManager::get<GeometryCache>();
auto pipeline = args->_pipeline; auto shapePipeline = args->_shapePipeline;
if (!pipeline) { if (!shapePipeline) {
pipeline = _isSolid ? geometryCache->getOpaqueShapePipeline() : geometryCache->getWireShapePipeline(); shapePipeline = _isSolid ? geometryCache->getOpaqueShapePipeline() : geometryCache->getWireShapePipeline();
} }
transform.setScale(dimensions); transform.setScale(dimensions);
batch->setModelTransform(transform); batch->setModelTransform(transform);
if (_isSolid) { if (_isSolid) {
geometryCache->renderSolidShapeInstance(*batch, _shape, cubeColor, pipeline); geometryCache->renderSolidShapeInstance(args, *batch, _shape, cubeColor, shapePipeline);
} else { } else {
geometryCache->renderWireShapeInstance(*batch, _shape, cubeColor, pipeline); geometryCache->renderWireShapeInstance(args, *batch, _shape, cubeColor, shapePipeline);
} }
} }
} }

View file

@ -44,15 +44,15 @@ void Sphere3DOverlay::render(RenderArgs* args) {
batch->setModelTransform(transform); batch->setModelTransform(transform);
auto geometryCache = DependencyManager::get<GeometryCache>(); auto geometryCache = DependencyManager::get<GeometryCache>();
auto pipeline = args->_pipeline; auto shapePipeline = args->_shapePipeline;
if (!pipeline) { if (!shapePipeline) {
pipeline = _isSolid ? geometryCache->getOpaqueShapePipeline() : geometryCache->getWireShapePipeline(); shapePipeline = _isSolid ? geometryCache->getOpaqueShapePipeline() : geometryCache->getWireShapePipeline();
} }
if (_isSolid) { if (_isSolid) {
geometryCache->renderSolidSphereInstance(*batch, sphereColor, pipeline); geometryCache->renderSolidSphereInstance(args, *batch, sphereColor, shapePipeline);
} else { } else {
geometryCache->renderWireSphereInstance(*batch, sphereColor, pipeline); geometryCache->renderWireSphereInstance(args, *batch, sphereColor, shapePipeline);
} }
} }
} }

View file

@ -137,8 +137,8 @@ void Text3DOverlay::render(RenderArgs* args) {
// Text renderer sets its own pipeline, // Text renderer sets its own pipeline,
_textRenderer->draw(batch, 0, 0, getText(), textColor, glm::vec2(-1.0f), getDrawInFront()); _textRenderer->draw(batch, 0, 0, getText(), textColor, glm::vec2(-1.0f), getDrawInFront());
// so before we continue, we must reset the pipeline // so before we continue, we must reset the pipeline
batch.setPipeline(args->_pipeline->pipeline); batch.setPipeline(args->_shapePipeline->pipeline);
args->_pipeline->prepare(batch); args->_shapePipeline->prepare(batch, args);
} }
const render::ShapeKey Text3DOverlay::getShapeKey() { const render::ShapeKey Text3DOverlay::getShapeKey() {

View file

@ -610,7 +610,7 @@ void Avatar::render(RenderArgs* renderArgs) {
if (showCollisionShapes && shouldRenderHead(renderArgs) && _skeletonModel->isRenderable()) { if (showCollisionShapes && shouldRenderHead(renderArgs) && _skeletonModel->isRenderable()) {
PROFILE_RANGE_BATCH(batch, __FUNCTION__":skeletonBoundingCollisionShapes"); PROFILE_RANGE_BATCH(batch, __FUNCTION__":skeletonBoundingCollisionShapes");
const float BOUNDING_SHAPE_ALPHA = 0.7f; const float BOUNDING_SHAPE_ALPHA = 0.7f;
_skeletonModel->renderBoundingCollisionShapes(*renderArgs->_batch, getUniformScale(), BOUNDING_SHAPE_ALPHA); _skeletonModel->renderBoundingCollisionShapes(renderArgs, *renderArgs->_batch, getUniformScale(), BOUNDING_SHAPE_ALPHA);
} }
if (showReceiveStats || showNamesAboveHeads) { if (showReceiveStats || showNamesAboveHeads) {

View file

@ -322,20 +322,20 @@ void SkeletonModel::computeBoundingShape() {
_boundingCapsuleLocalOffset = invScale * offset; _boundingCapsuleLocalOffset = invScale * offset;
} }
void SkeletonModel::renderBoundingCollisionShapes(gpu::Batch& batch, float scale, float alpha) { void SkeletonModel::renderBoundingCollisionShapes(RenderArgs* args, gpu::Batch& batch, float scale, float alpha) {
auto geometryCache = DependencyManager::get<GeometryCache>(); auto geometryCache = DependencyManager::get<GeometryCache>();
// draw a blue sphere at the capsule top point // draw a blue sphere at the capsule top point
glm::vec3 topPoint = _translation + getRotation() * (scale * (_boundingCapsuleLocalOffset + (0.5f * _boundingCapsuleHeight) * Vectors::UNIT_Y)); glm::vec3 topPoint = _translation + getRotation() * (scale * (_boundingCapsuleLocalOffset + (0.5f * _boundingCapsuleHeight) * Vectors::UNIT_Y));
batch.setModelTransform(Transform().setTranslation(topPoint).postScale(scale * _boundingCapsuleRadius)); batch.setModelTransform(Transform().setTranslation(topPoint).postScale(scale * _boundingCapsuleRadius));
geometryCache->renderSolidSphereInstance(batch, glm::vec4(0.6f, 0.6f, 0.8f, alpha)); geometryCache->renderSolidSphereInstance(args, batch, glm::vec4(0.6f, 0.6f, 0.8f, alpha));
// draw a yellow sphere at the capsule bottom point // draw a yellow sphere at the capsule bottom point
glm::vec3 bottomPoint = topPoint - glm::vec3(0.0f, scale * _boundingCapsuleHeight, 0.0f); glm::vec3 bottomPoint = topPoint - glm::vec3(0.0f, scale * _boundingCapsuleHeight, 0.0f);
glm::vec3 axis = topPoint - bottomPoint; glm::vec3 axis = topPoint - bottomPoint;
batch.setModelTransform(Transform().setTranslation(bottomPoint).postScale(scale * _boundingCapsuleRadius)); batch.setModelTransform(Transform().setTranslation(bottomPoint).postScale(scale * _boundingCapsuleRadius));
geometryCache->renderSolidSphereInstance(batch, glm::vec4(0.8f, 0.8f, 0.6f, alpha)); geometryCache->renderSolidSphereInstance(args, batch, glm::vec4(0.8f, 0.8f, 0.6f, alpha));
// draw a green cylinder between the two points // draw a green cylinder between the two points
glm::vec3 origin(0.0f); glm::vec3 origin(0.0f);

View file

@ -96,7 +96,7 @@ public:
/// \return whether or not the head was found. /// \return whether or not the head was found.
glm::vec3 getDefaultEyeModelPosition() const; glm::vec3 getDefaultEyeModelPosition() const;
void renderBoundingCollisionShapes(gpu::Batch& batch, float scale, float alpha); void renderBoundingCollisionShapes(RenderArgs* args, gpu::Batch& batch, float scale, float alpha);
float getBoundingCapsuleRadius() const { return _boundingCapsuleRadius; } float getBoundingCapsuleRadius() const { return _boundingCapsuleRadius; }
float getBoundingCapsuleHeight() const { return _boundingCapsuleHeight; } float getBoundingCapsuleHeight() const { return _boundingCapsuleHeight; }
const glm::vec3 getBoundingCapsuleOffset() const { return _boundingCapsuleLocalOffset; } const glm::vec3 getBoundingCapsuleOffset() const { return _boundingCapsuleLocalOffset; }

View file

@ -378,7 +378,7 @@ void RenderableModelEntityItem::render(RenderArgs* args) {
auto shapeTransform = getTransformToCenter(success); auto shapeTransform = getTransformToCenter(success);
if (success) { if (success) {
batch.setModelTransform(shapeTransform); // we want to include the scale as well batch.setModelTransform(shapeTransform); // we want to include the scale as well
DependencyManager::get<GeometryCache>()->renderWireCubeInstance(batch, greenColor); DependencyManager::get<GeometryCache>()->renderWireCubeInstance(args, batch, greenColor);
} }
return; return;
} }

View file

@ -128,9 +128,9 @@ void RenderableShapeEntityItem::render(RenderArgs* args) {
auto pipeline = color.a < 1.0f ? geometryCache->getTransparentShapePipeline() : geometryCache->getOpaqueShapePipeline(); auto pipeline = color.a < 1.0f ? geometryCache->getTransparentShapePipeline() : geometryCache->getOpaqueShapePipeline();
if (render::ShapeKey(args->_globalShapeKey).isWireframe()) { if (render::ShapeKey(args->_globalShapeKey).isWireframe()) {
geometryCache->renderWireShapeInstance(batch, MAPPING[_shape], color, pipeline); geometryCache->renderWireShapeInstance(args, batch, MAPPING[_shape], color, pipeline);
} else { } else {
geometryCache->renderSolidShapeInstance(batch, MAPPING[_shape], color, pipeline); geometryCache->renderSolidShapeInstance(args, batch, MAPPING[_shape], color, pipeline);
} }
} }

View file

@ -221,10 +221,10 @@ void RenderableZoneEntityItem::render(RenderArgs* args) {
if (getShapeType() == SHAPE_TYPE_SPHERE) { if (getShapeType() == SHAPE_TYPE_SPHERE) {
shapeTransform.postScale(SPHERE_ENTITY_SCALE); shapeTransform.postScale(SPHERE_ENTITY_SCALE);
batch.setModelTransform(shapeTransform); batch.setModelTransform(shapeTransform);
geometryCache->renderWireSphereInstance(batch, DEFAULT_COLOR); geometryCache->renderWireSphereInstance(args, batch, DEFAULT_COLOR);
} else { } else {
batch.setModelTransform(shapeTransform); batch.setModelTransform(shapeTransform);
geometryCache->renderWireCubeInstance(batch, DEFAULT_COLOR); geometryCache->renderWireCubeInstance(args, batch, DEFAULT_COLOR);
} }
break; break;
} }
@ -554,11 +554,13 @@ void RenderableZoneEntityItemMeta::setProceduralUserData(QString userData) {
void RenderableZoneEntityItemMeta::render(RenderArgs* args) { void RenderableZoneEntityItemMeta::render(RenderArgs* args) {
if (!_stage) { if (!_stage) {
_stage = DependencyManager::get<DeferredLightingEffect>()->getLightStage(); _stage = args->_scene->getStage<LightStage>();
assert(_stage);
} }
if (!_backgroundStage) { if (!_backgroundStage) {
_backgroundStage = DependencyManager::get<DeferredLightingEffect>()->getBackgroundStage(); _backgroundStage = args->_scene->getStage<BackgroundStage>();
assert(_backgroundStage);
} }
{ // Sun { // Sun

View file

@ -197,8 +197,12 @@ public:
*lockWaitOut = (endLock - start); *lockWaitOut = (endLock - start);
} }
std::vector<SharedNodePointer> nodes(_nodeHash.size()); // Size of _nodeHash could change at any time,
std::transform(_nodeHash.cbegin(), _nodeHash.cend(), nodes.begin(), [](const NodeHash::value_type& it) { // so reserve enough memory for the current size
// and then back insert all the nodes found
std::vector<SharedNodePointer> nodes;
nodes.reserve(_nodeHash.size());
std::transform(_nodeHash.cbegin(), _nodeHash.cend(), std::back_inserter(nodes), [&](const NodeHash::value_type& it) {
return it.second; return it.second;
}); });
auto endTransform = usecTimestampNow(); auto endTransform = usecTimestampNow();

View file

@ -13,6 +13,8 @@
#include <gpu/Context.h> #include <gpu/Context.h>
std::string BackgroundStage::_stageName { "BACKGROUND_STAGE"};
BackgroundStage::Index BackgroundStage::findBackground(const BackgroundPointer& background) const { BackgroundStage::Index BackgroundStage::findBackground(const BackgroundPointer& background) const {
auto found = _backgroundMap.find(background); auto found = _backgroundMap.find(background);
if (found != _backgroundMap.end()) { if (found != _backgroundMap.end()) {
@ -52,15 +54,15 @@ BackgroundStage::BackgroundPointer BackgroundStage::removeBackground(Index index
void DrawBackgroundStage::run(const render::RenderContextPointer& renderContext, const Inputs& inputs) { void DrawBackgroundStage::run(const render::RenderContextPointer& renderContext, const Inputs& inputs) {
const auto& lightingModel = inputs; const auto& lightingModel = inputs;
if (!lightingModel->isBackgroundEnabled()) { if (!lightingModel->isBackgroundEnabled()) {
return; return;
} }
// Background rendering decision // Background rendering decision
auto backgroundStage = DependencyManager::get<DeferredLightingEffect>()->getBackgroundStage(); auto backgroundStage = renderContext->_scene->getStage<BackgroundStage>();
assert(backgroundStage);
model::SunSkyStagePointer background; model::SunSkyStagePointer background;
model::SkyboxPointer skybox; model::SkyboxPointer skybox;
if (backgroundStage->_currentFrame._backgrounds.size()) { if (backgroundStage->_currentFrame._backgrounds.size()) {
@ -68,11 +70,8 @@ void DrawBackgroundStage::run(const render::RenderContextPointer& renderContext,
auto background = backgroundStage->getBackground(backgroundId); auto background = backgroundStage->getBackground(backgroundId);
if (background) { if (background) {
skybox = background->getSkybox(); skybox = background->getSkybox();
} }
} else {
skybox = DependencyManager::get<DeferredLightingEffect>()->getDefaultSkybox();
} }
/* auto backgroundMode = skyStage->getBackgroundMode(); /* auto backgroundMode = skyStage->getBackgroundMode();
switch (backgroundMode) { switch (backgroundMode) {
@ -137,4 +136,15 @@ void DrawBackgroundStage::run(const render::RenderContextPointer& renderContext,
} }
*/ */
} }
BackgroundStageSetup::BackgroundStageSetup() {
}
void BackgroundStageSetup::run(const render::RenderContextPointer& renderContext) {
auto stage = renderContext->_scene->getStage(BackgroundStage::getName());
if (!stage) {
renderContext->_scene->resetStage(BackgroundStage::getName(), std::make_shared<BackgroundStage>());
}
}

View file

@ -15,13 +15,17 @@
#include <set> #include <set>
#include <unordered_map> #include <unordered_map>
#include <render/IndexedContainer.h> #include <render/IndexedContainer.h>
#include <render/Stage.h>
#include "LightingModel.h" #include "LightingModel.h"
// Background stage to set up background-related rendering tasks // Background stage to set up background-related rendering tasks
class BackgroundStage { class BackgroundStage : public render::Stage {
public: public:
static std::string _stageName;
static const std::string& getName() { return _stageName; }
using Index = render::indexed_container::Index; using Index = render::indexed_container::Index;
static const Index INVALID_INDEX { render::indexed_container::INVALID_INDEX }; static const Index INVALID_INDEX { render::indexed_container::INVALID_INDEX };
static bool isIndexInvalid(Index index) { return index == INVALID_INDEX; } static bool isIndexInvalid(Index index) { return index == INVALID_INDEX; }
@ -66,6 +70,15 @@ public:
}; };
using BackgroundStagePointer = std::shared_ptr<BackgroundStage>; using BackgroundStagePointer = std::shared_ptr<BackgroundStage>;
class BackgroundStageSetup {
public:
using JobModel = render::Job::Model<BackgroundStageSetup>;
BackgroundStageSetup();
void run(const render::RenderContextPointer& renderContext);
protected:
};
class DrawBackgroundStage { class DrawBackgroundStage {
public: public:

View file

@ -432,9 +432,10 @@ void DebugDeferredBuffer::run(const RenderContextPointer& renderContext, const I
batch.setResourceTexture(Lighting, deferredFramebuffer->getLightingTexture()); batch.setResourceTexture(Lighting, deferredFramebuffer->getLightingTexture());
} }
auto deferredLightingEffect = DependencyManager::get<DeferredLightingEffect>(); auto lightStage = renderContext->_scene->getStage<LightStage>();
assert(deferredLightingEffect->getLightStage()->getNumLights() > 0); assert(lightStage);
auto lightAndShadow = deferredLightingEffect->getLightStage()->getLightAndShadow(0); assert(lightStage->getNumLights() > 0);
auto lightAndShadow = lightStage->getLightAndShadow(0);
const auto& globalShadow = lightAndShadow.second; const auto& globalShadow = lightAndShadow.second;
if (globalShadow) { if (globalShadow) {
batch.setResourceTexture(Shadow, globalShadow->map); batch.setResourceTexture(Shadow, globalShadow->map);

View file

@ -99,75 +99,35 @@ void DeferredLightingEffect::init() {
loadLightProgram(deferred_light_vert, local_lights_shading_frag, true, _localLight, _localLightLocations); loadLightProgram(deferred_light_vert, local_lights_shading_frag, true, _localLight, _localLightLocations);
loadLightProgram(deferred_light_vert, local_lights_drawOutline_frag, true, _localLightOutline, _localLightOutlineLocations); loadLightProgram(deferred_light_vert, local_lights_drawOutline_frag, true, _localLightOutline, _localLightOutlineLocations);
// Light Stage and clusters
_lightStage = std::make_shared<LightStage>();
// Allocate a global light representing the Global Directional light casting shadow (the sun) and the ambient light
_allocatedLights.push_back(std::make_shared<model::Light>());
model::LightPointer lp = _allocatedLights[0];
lp->setType(model::Light::SUN);
lp->setDirection(glm::vec3(-1.0f));
lp->setColor(glm::vec3(1.0f));
lp->setIntensity(1.0f);
lp->setType(model::Light::SUN);
lp->setAmbientSpherePreset(gpu::SphericalHarmonics::Preset::OLD_TOWN_SQUARE);
// Add the global light to the light stage (for later shadow rendering)
_globalLights.push_back(_lightStage->addLight(lp));
_lightStage->addShadow(_globalLights[0]);
_backgroundStage = std::make_shared<BackgroundStage>();
auto textureCache = DependencyManager::get<TextureCache>();
{
PROFILE_RANGE(render, "Process Default Skybox");
auto textureCache = DependencyManager::get<TextureCache>();
auto skyboxUrl = PathUtils::resourcesPath().toStdString() + "images/Default-Sky-9-cubemap.ktx";
_defaultSkyboxTexture = gpu::Texture::unserialize(skyboxUrl);
_defaultSkyboxAmbientTexture = _defaultSkyboxTexture;
_defaultSkybox->setCubemap(_defaultSkyboxTexture);
}
lp->setAmbientIntensity(0.5f);
lp->setAmbientMap(_defaultSkyboxAmbientTexture);
auto irradianceSH = _defaultSkyboxAmbientTexture->getIrradiance();
if (irradianceSH) {
lp->setAmbientSphere((*irradianceSH));
}
} }
void DeferredLightingEffect::setupKeyLightBatch(gpu::Batch& batch, int lightBufferUnit, int ambientBufferUnit, int skyboxCubemapUnit) { void DeferredLightingEffect::setupKeyLightBatch(const RenderArgs* args, gpu::Batch& batch, int lightBufferUnit, int ambientBufferUnit, int skyboxCubemapUnit) {
PerformanceTimer perfTimer("DLE->setupBatch()"); PerformanceTimer perfTimer("DLE->setupBatch()");
model::LightPointer keySunLight; model::LightPointer keySunLight;
if (_lightStage && _lightStage->_currentFrame._sunLights.size()) { auto lightStage = args->_scene->getStage<LightStage>();
keySunLight = _lightStage->getLight(_lightStage->_currentFrame._sunLights.front()); if (lightStage && lightStage->_currentFrame._sunLights.size()) {
} else { keySunLight = lightStage->getLight(lightStage->_currentFrame._sunLights.front());
keySunLight = _allocatedLights[_globalLights.front()];
} }
model::LightPointer keyAmbiLight; model::LightPointer keyAmbiLight;
if (_lightStage && _lightStage->_currentFrame._ambientLights.size()) { if (lightStage && lightStage->_currentFrame._ambientLights.size()) {
keyAmbiLight = _lightStage->getLight(_lightStage->_currentFrame._ambientLights.front()); keyAmbiLight = lightStage->getLight(lightStage->_currentFrame._ambientLights.front());
} else {
keyAmbiLight = _allocatedLights[_globalLights.front()];
} }
if (lightBufferUnit >= 0) { if (keySunLight) {
batch.setUniformBuffer(lightBufferUnit, keySunLight->getLightSchemaBuffer()); if (lightBufferUnit >= 0) {
} batch.setUniformBuffer(lightBufferUnit, keySunLight->getLightSchemaBuffer());
if (ambientBufferUnit >= 0) { }
batch.setUniformBuffer(ambientBufferUnit, keyAmbiLight->getAmbientSchemaBuffer());
} }
if (keyAmbiLight->getAmbientMap() && (skyboxCubemapUnit >= 0)) { if (keyAmbiLight) {
batch.setResourceTexture(skyboxCubemapUnit, keyAmbiLight->getAmbientMap()); if (ambientBufferUnit >= 0) {
batch.setUniformBuffer(ambientBufferUnit, keyAmbiLight->getAmbientSchemaBuffer());
}
if (keyAmbiLight->getAmbientMap() && (skyboxCubemapUnit >= 0)) {
batch.setResourceTexture(skyboxCubemapUnit, keyAmbiLight->getAmbientMap());
}
} }
} }
@ -266,21 +226,6 @@ static void loadLightProgram(const char* vertSource, const char* fragSource, boo
} }
void DeferredLightingEffect::setGlobalLight(const model::LightPointer& light) {
/* auto globalLight = _allocatedLights.front();
globalLight->setDirection(light->getDirection());
globalLight->setColor(light->getColor());
globalLight->setIntensity(light->getIntensity());
globalLight->setAmbientIntensity(light->getAmbientIntensity());
globalLight->setAmbientSphere(light->getAmbientSphere());
globalLight->setAmbientMap(light->getAmbientMap());*/
}
const model::LightPointer& DeferredLightingEffect::getGlobalLight() const {
return _allocatedLights.front();
}
#include <shared/Shapes.h> #include <shared/Shapes.h>
model::MeshPointer DeferredLightingEffect::getPointLightMesh() { model::MeshPointer DeferredLightingEffect::getPointLightMesh() {
@ -483,8 +428,9 @@ void PrepareDeferred::run(const RenderContextPointer& renderContext, const Input
// Prepare a fresh Light Frame // Prepare a fresh Light Frame
auto deferredLightingEffect = DependencyManager::get<DeferredLightingEffect>(); auto lightStage = renderContext->_scene->getStage<LightStage>();
deferredLightingEffect->getLightStage()->_currentFrame.clear(); assert(lightStage);
lightStage->_currentFrame.clear();
} }
@ -547,8 +493,10 @@ void RenderDeferredSetup::run(const render::RenderContextPointer& renderContext,
// Global directional light and ambient pass // Global directional light and ambient pass
assert(deferredLightingEffect->getLightStage()->getNumLights() > 0); auto lightStage = renderContext->_scene->getStage<LightStage>();
auto lightAndShadow = deferredLightingEffect->getLightStage()->getLightAndShadow(0); assert(lightStage);
assert(lightStage->getNumLights() > 0);
auto lightAndShadow = lightStage->getLightAndShadow(0);
const auto& globalShadow = lightAndShadow.second; const auto& globalShadow = lightAndShadow.second;
// Bind the shadow buffer // Bind the shadow buffer
@ -558,7 +506,8 @@ void RenderDeferredSetup::run(const render::RenderContextPointer& renderContext,
auto& program = deferredLightingEffect->_directionalSkyboxLight; auto& program = deferredLightingEffect->_directionalSkyboxLight;
LightLocationsPtr locations = deferredLightingEffect->_directionalSkyboxLightLocations; LightLocationsPtr locations = deferredLightingEffect->_directionalSkyboxLightLocations;
const auto& keyLight = deferredLightingEffect->_allocatedLights[deferredLightingEffect->_globalLights.front()];
auto keyLight = lightStage->getLight(0);
// Setup the global directional pass pipeline // Setup the global directional pass pipeline
{ {
@ -597,7 +546,7 @@ void RenderDeferredSetup::run(const render::RenderContextPointer& renderContext,
batch._glUniform4fv(locations->texcoordFrameTransform, 1, reinterpret_cast< const float* >(&textureFrameTransform)); batch._glUniform4fv(locations->texcoordFrameTransform, 1, reinterpret_cast< const float* >(&textureFrameTransform));
// Setup the global lighting // Setup the global lighting
deferredLightingEffect->setupKeyLightBatch(batch, locations->lightBufferUnit, locations->ambientBufferUnit, SKYBOX_MAP_UNIT); deferredLightingEffect->setupKeyLightBatch(args, batch, locations->lightBufferUnit, locations->ambientBufferUnit, SKYBOX_MAP_UNIT);
batch.draw(gpu::TRIANGLE_STRIP, 4); batch.draw(gpu::TRIANGLE_STRIP, 4);
@ -749,3 +698,66 @@ void RenderDeferred::run(const RenderContextPointer& renderContext, const Inputs
auto config = std::static_pointer_cast<Config>(renderContext->jobConfig); auto config = std::static_pointer_cast<Config>(renderContext->jobConfig);
config->setGPUBatchRunTime(_gpuTimer->getGPUAverage(), _gpuTimer->getBatchAverage()); config->setGPUBatchRunTime(_gpuTimer->getGPUAverage(), _gpuTimer->getBatchAverage());
} }
void DefaultLightingSetup::run(const RenderContextPointer& renderContext) {
if (!_defaultLight || !_defaultBackground) {
if (!_defaultSkyboxTexture) {
auto textureCache = DependencyManager::get<TextureCache>();
{
PROFILE_RANGE(render, "Process Default Skybox");
auto textureCache = DependencyManager::get<TextureCache>();
auto skyboxUrl = PathUtils::resourcesPath().toStdString() + "images/Default-Sky-9-cubemap.ktx";
_defaultSkyboxTexture = gpu::Texture::unserialize(skyboxUrl);
_defaultSkyboxAmbientTexture = _defaultSkyboxTexture;
_defaultSkybox->setCubemap(_defaultSkyboxTexture);
}
}
auto lightStage = renderContext->_scene->getStage<LightStage>();
if (lightStage) {
// Allocate a default global light directional and ambient
auto lp = std::make_shared<model::Light>();
lp->setType(model::Light::SUN);
lp->setDirection(glm::vec3(-1.0f));
lp->setColor(glm::vec3(1.0f));
lp->setIntensity(1.0f);
lp->setType(model::Light::SUN);
lp->setAmbientSpherePreset(gpu::SphericalHarmonics::Preset::OLD_TOWN_SQUARE);
lp->setAmbientIntensity(0.5f);
lp->setAmbientMap(_defaultSkyboxAmbientTexture);
auto irradianceSH = _defaultSkyboxAmbientTexture->getIrradiance();
if (irradianceSH) {
lp->setAmbientSphere((*irradianceSH));
}
// capture default light
_defaultLight = lp;
// Add the global light to the light stage (for later shadow rendering)
_defaultLightID = lightStage->addLight(lp);
lightStage->addShadow(_defaultLightID);
}
auto backgroundStage = renderContext->_scene->getStage<BackgroundStage>();
if (backgroundStage) {
auto background = std::make_shared<model::SunSkyStage>();
background->setSkybox(_defaultSkybox);
// capture deault background
_defaultBackground = background;
// Add the global light to the light stage (for later shadow rendering)
_defaultBackgroundID = backgroundStage->addBackground(_defaultBackground);
}
}
}

View file

@ -47,30 +47,16 @@ class DeferredLightingEffect : public Dependency {
public: public:
void init(); void init();
void setupKeyLightBatch(gpu::Batch& batch, int lightBufferUnit, int ambientBufferUnit, int skyboxCubemapUnit); void setupKeyLightBatch(const RenderArgs* args, gpu::Batch& batch, int lightBufferUnit, int ambientBufferUnit, int skyboxCubemapUnit);
void unsetKeyLightBatch(gpu::Batch& batch, int lightBufferUnit, int ambientBufferUnit, int skyboxCubemapUnit); void unsetKeyLightBatch(gpu::Batch& batch, int lightBufferUnit, int ambientBufferUnit, int skyboxCubemapUnit);
// update global lighting
void setGlobalLight(const model::LightPointer& light);
const model::LightPointer& getGlobalLight() const;
const LightStagePointer& getLightStage() { return _lightStage; }
const BackgroundStagePointer& getBackgroundStage() { return _backgroundStage; }
void setShadowMapEnabled(bool enable) { _shadowMapEnabled = enable; }; void setShadowMapEnabled(bool enable) { _shadowMapEnabled = enable; };
void setAmbientOcclusionEnabled(bool enable) { _ambientOcclusionEnabled = enable; } void setAmbientOcclusionEnabled(bool enable) { _ambientOcclusionEnabled = enable; }
bool isAmbientOcclusionEnabled() const { return _ambientOcclusionEnabled; } bool isAmbientOcclusionEnabled() const { return _ambientOcclusionEnabled; }
model::SkyboxPointer getDefaultSkybox() const { return _defaultSkybox; }
gpu::TexturePointer getDefaultSkyboxTexture() const { return _defaultSkyboxTexture; }
gpu::TexturePointer getDefaultSkyboxAmbientTexture() const { return _defaultSkyboxAmbientTexture; }
private: private:
DeferredLightingEffect() = default; DeferredLightingEffect() = default;
LightStagePointer _lightStage;
BackgroundStagePointer _backgroundStage;
bool _shadowMapEnabled{ false }; bool _shadowMapEnabled{ false };
bool _ambientOcclusionEnabled{ false }; bool _ambientOcclusionEnabled{ false };
@ -97,15 +83,6 @@ private:
LightLocationsPtr _localLightLocations; LightLocationsPtr _localLightLocations;
LightLocationsPtr _localLightOutlineLocations; LightLocationsPtr _localLightOutlineLocations;
using Lights = std::vector<model::LightPointer>;
Lights _allocatedLights;
std::vector<int> _globalLights;
model::SkyboxPointer _defaultSkybox { new ProceduralSkybox() };
gpu::TexturePointer _defaultSkyboxTexture;
gpu::TexturePointer _defaultSkyboxAmbientTexture;
friend class LightClusteringPass; friend class LightClusteringPass;
friend class RenderDeferredSetup; friend class RenderDeferredSetup;
friend class RenderDeferredLocals; friend class RenderDeferredLocals;
@ -195,6 +172,20 @@ protected:
gpu::RangeTimerPointer _gpuTimer; gpu::RangeTimerPointer _gpuTimer;
}; };
class DefaultLightingSetup {
public:
using JobModel = render::Job::Model<DefaultLightingSetup>;
void run(const render::RenderContextPointer& renderContext);
protected:
model::LightPointer _defaultLight;
LightStage::Index _defaultLightID{ LightStage::INVALID_INDEX };
model::SunSkyStagePointer _defaultBackground;
BackgroundStage::Index _defaultBackgroundID{ BackgroundStage::INVALID_INDEX };
model::SkyboxPointer _defaultSkybox { new ProceduralSkybox() };
gpu::TexturePointer _defaultSkyboxTexture;
gpu::TexturePointer _defaultSkyboxAmbientTexture;
};
#endif // hifi_DeferredLightingEffect_h #endif // hifi_DeferredLightingEffect_h

View file

@ -455,7 +455,7 @@ _nextID(0) {
buildShapes(); buildShapes();
GeometryCache::_simpleOpaquePipeline = GeometryCache::_simpleOpaquePipeline =
std::make_shared<render::ShapePipeline>(getSimplePipeline(false, false, true, false), nullptr, std::make_shared<render::ShapePipeline>(getSimplePipeline(false, false, true, false), nullptr,
[](const render::ShapePipeline&, gpu::Batch& batch) { [](const render::ShapePipeline&, gpu::Batch& batch, RenderArgs* args) {
// Set the defaults needed for a simple program // Set the defaults needed for a simple program
batch.setResourceTexture(render::ShapePipeline::Slot::MAP::ALBEDO, batch.setResourceTexture(render::ShapePipeline::Slot::MAP::ALBEDO,
DependencyManager::get<TextureCache>()->getWhiteTexture()); DependencyManager::get<TextureCache>()->getWhiteTexture());
@ -463,7 +463,7 @@ _nextID(0) {
); );
GeometryCache::_simpleTransparentPipeline = GeometryCache::_simpleTransparentPipeline =
std::make_shared<render::ShapePipeline>(getSimplePipeline(false, true, true, false), nullptr, std::make_shared<render::ShapePipeline>(getSimplePipeline(false, true, true, false), nullptr,
[](const render::ShapePipeline&, gpu::Batch& batch) { [](const render::ShapePipeline&, gpu::Batch& batch, RenderArgs* args) {
// Set the defaults needed for a simple program // Set the defaults needed for a simple program
batch.setResourceTexture(render::ShapePipeline::Slot::MAP::ALBEDO, batch.setResourceTexture(render::ShapePipeline::Slot::MAP::ALBEDO,
DependencyManager::get<TextureCache>()->getWhiteTexture()); DependencyManager::get<TextureCache>()->getWhiteTexture());
@ -471,7 +471,7 @@ _nextID(0) {
); );
GeometryCache::_simpleWirePipeline = GeometryCache::_simpleWirePipeline =
std::make_shared<render::ShapePipeline>(getSimplePipeline(false, false, true, true), nullptr, std::make_shared<render::ShapePipeline>(getSimplePipeline(false, false, true, true), nullptr,
[](const render::ShapePipeline&, gpu::Batch& batch) {}); [](const render::ShapePipeline&, gpu::Batch& batch, RenderArgs* args) {});
} }
GeometryCache::~GeometryCache() { GeometryCache::~GeometryCache() {
@ -1938,7 +1938,7 @@ uint32_t toCompactColor(const glm::vec4& color) {
static const size_t INSTANCE_COLOR_BUFFER = 0; static const size_t INSTANCE_COLOR_BUFFER = 0;
void renderInstances(gpu::Batch& batch, const glm::vec4& color, bool isWire, void renderInstances(RenderArgs* args, gpu::Batch& batch, const glm::vec4& color, bool isWire,
const render::ShapePipelinePointer& pipeline, GeometryCache::Shape shape) { const render::ShapePipelinePointer& pipeline, GeometryCache::Shape shape) {
// Add pipeline to name // Add pipeline to name
std::string instanceName = (isWire ? "wire_shapes_" : "solid_shapes_") + std::to_string(shape) + "_" + std::to_string(std::hash<render::ShapePipelinePointer>()(pipeline)); std::string instanceName = (isWire ? "wire_shapes_" : "solid_shapes_") + std::to_string(shape) + "_" + std::to_string(std::hash<render::ShapePipelinePointer>()(pipeline));
@ -1951,9 +1951,9 @@ void renderInstances(gpu::Batch& batch, const glm::vec4& color, bool isWire,
} }
// Add call to named buffer // Add call to named buffer
batch.setupNamedCalls(instanceName, [isWire, pipeline, shape](gpu::Batch& batch, gpu::Batch::NamedBatchData& data) { batch.setupNamedCalls(instanceName, [args, isWire, pipeline, shape](gpu::Batch& batch, gpu::Batch::NamedBatchData& data) {
batch.setPipeline(pipeline->pipeline); batch.setPipeline(pipeline->pipeline);
pipeline->prepare(batch); pipeline->prepare(batch, args);
if (isWire) { if (isWire) {
DependencyManager::get<GeometryCache>()->renderWireShapeInstances(batch, shape, data.count(), data.buffers[INSTANCE_COLOR_BUFFER]); DependencyManager::get<GeometryCache>()->renderWireShapeInstances(batch, shape, data.count(), data.buffers[INSTANCE_COLOR_BUFFER]);
@ -1963,28 +1963,28 @@ void renderInstances(gpu::Batch& batch, const glm::vec4& color, bool isWire,
}); });
} }
void GeometryCache::renderSolidShapeInstance(gpu::Batch& batch, GeometryCache::Shape shape, const glm::vec4& color, const render::ShapePipelinePointer& pipeline) { void GeometryCache::renderSolidShapeInstance(RenderArgs* args, gpu::Batch& batch, GeometryCache::Shape shape, const glm::vec4& color, const render::ShapePipelinePointer& pipeline) {
renderInstances(batch, color, false, pipeline, shape); renderInstances(args, batch, color, false, pipeline, shape);
} }
void GeometryCache::renderWireShapeInstance(gpu::Batch& batch, GeometryCache::Shape shape, const glm::vec4& color, const render::ShapePipelinePointer& pipeline) { void GeometryCache::renderWireShapeInstance(RenderArgs* args, gpu::Batch& batch, GeometryCache::Shape shape, const glm::vec4& color, const render::ShapePipelinePointer& pipeline) {
renderInstances(batch, color, true, pipeline, shape); renderInstances(args, batch, color, true, pipeline, shape);
} }
void GeometryCache::renderSolidSphereInstance(gpu::Batch& batch, const glm::vec4& color, const render::ShapePipelinePointer& pipeline) { void GeometryCache::renderSolidSphereInstance(RenderArgs* args, gpu::Batch& batch, const glm::vec4& color, const render::ShapePipelinePointer& pipeline) {
renderInstances(batch, color, false, pipeline, GeometryCache::Sphere); renderInstances(args, batch, color, false, pipeline, GeometryCache::Sphere);
} }
void GeometryCache::renderWireSphereInstance(gpu::Batch& batch, const glm::vec4& color, const render::ShapePipelinePointer& pipeline) { void GeometryCache::renderWireSphereInstance(RenderArgs* args, gpu::Batch& batch, const glm::vec4& color, const render::ShapePipelinePointer& pipeline) {
renderInstances(batch, color, true, pipeline, GeometryCache::Sphere); renderInstances(args, batch, color, true, pipeline, GeometryCache::Sphere);
} }
// Enable this in a debug build to cause 'box' entities to iterate through all the // Enable this in a debug build to cause 'box' entities to iterate through all the
// available shape types, both solid and wireframes // available shape types, both solid and wireframes
//#define DEBUG_SHAPES //#define DEBUG_SHAPES
void GeometryCache::renderSolidCubeInstance(gpu::Batch& batch, const glm::vec4& color, const render::ShapePipelinePointer& pipeline) { void GeometryCache::renderSolidCubeInstance(RenderArgs* args, gpu::Batch& batch, const glm::vec4& color, const render::ShapePipelinePointer& pipeline) {
#ifdef DEBUG_SHAPES #ifdef DEBUG_SHAPES
static auto startTime = usecTimestampNow(); static auto startTime = usecTimestampNow();
renderInstances(INSTANCE_NAME, batch, color, pipeline, [](gpu::Batch& batch, gpu::Batch::NamedBatchData& data) { renderInstances(INSTANCE_NAME, batch, color, pipeline, [](gpu::Batch& batch, gpu::Batch::NamedBatchData& data) {
@ -2018,11 +2018,11 @@ void GeometryCache::renderSolidCubeInstance(gpu::Batch& batch, const glm::vec4&
} }
}); });
#else #else
renderInstances(batch, color, false, pipeline, GeometryCache::Cube); renderInstances(args, batch, color, false, pipeline, GeometryCache::Cube);
#endif #endif
} }
void GeometryCache::renderWireCubeInstance(gpu::Batch& batch, const glm::vec4& color, const render::ShapePipelinePointer& pipeline) { void GeometryCache::renderWireCubeInstance(RenderArgs* args, gpu::Batch& batch, const glm::vec4& color, const render::ShapePipelinePointer& pipeline) {
static const std::string INSTANCE_NAME = __FUNCTION__; static const std::string INSTANCE_NAME = __FUNCTION__;
renderInstances(batch, color, true, pipeline, GeometryCache::Cube); renderInstances(args, batch, color, true, pipeline, GeometryCache::Cube);
} }

View file

@ -172,46 +172,46 @@ public:
void renderShapeInstances(gpu::Batch& batch, Shape shape, size_t count, gpu::BufferPointer& colorBuffer); void renderShapeInstances(gpu::Batch& batch, Shape shape, size_t count, gpu::BufferPointer& colorBuffer);
void renderWireShapeInstances(gpu::Batch& batch, Shape shape, size_t count, gpu::BufferPointer& colorBuffer); void renderWireShapeInstances(gpu::Batch& batch, Shape shape, size_t count, gpu::BufferPointer& colorBuffer);
void renderSolidShapeInstance(gpu::Batch& batch, Shape shape, const glm::vec4& color = glm::vec4(1), void renderSolidShapeInstance(RenderArgs* args, gpu::Batch& batch, Shape shape, const glm::vec4& color = glm::vec4(1),
const render::ShapePipelinePointer& pipeline = _simpleOpaquePipeline); const render::ShapePipelinePointer& pipeline = _simpleOpaquePipeline);
void renderSolidShapeInstance(gpu::Batch& batch, Shape shape, const glm::vec3& color, void renderSolidShapeInstance(RenderArgs* args, gpu::Batch& batch, Shape shape, const glm::vec3& color,
const render::ShapePipelinePointer& pipeline = _simpleOpaquePipeline) { const render::ShapePipelinePointer& pipeline = _simpleOpaquePipeline) {
renderSolidShapeInstance(batch, shape, glm::vec4(color, 1.0f), pipeline); renderSolidShapeInstance(args, batch, shape, glm::vec4(color, 1.0f), pipeline);
} }
void renderWireShapeInstance(gpu::Batch& batch, Shape shape, const glm::vec4& color = glm::vec4(1), void renderWireShapeInstance(RenderArgs* args, gpu::Batch& batch, Shape shape, const glm::vec4& color = glm::vec4(1),
const render::ShapePipelinePointer& pipeline = _simpleOpaquePipeline); const render::ShapePipelinePointer& pipeline = _simpleOpaquePipeline);
void renderWireShapeInstance(gpu::Batch& batch, Shape shape, const glm::vec3& color, void renderWireShapeInstance(RenderArgs* args, gpu::Batch& batch, Shape shape, const glm::vec3& color,
const render::ShapePipelinePointer& pipeline = _simpleOpaquePipeline) { const render::ShapePipelinePointer& pipeline = _simpleOpaquePipeline) {
renderWireShapeInstance(batch, shape, glm::vec4(color, 1.0f), pipeline); renderWireShapeInstance(args, batch, shape, glm::vec4(color, 1.0f), pipeline);
} }
void renderSolidSphereInstance(gpu::Batch& batch, const glm::vec4& color, void renderSolidSphereInstance(RenderArgs* args, gpu::Batch& batch, const glm::vec4& color,
const render::ShapePipelinePointer& pipeline = _simpleOpaquePipeline); const render::ShapePipelinePointer& pipeline = _simpleOpaquePipeline);
void renderSolidSphereInstance(gpu::Batch& batch, const glm::vec3& color, void renderSolidSphereInstance(RenderArgs* args, gpu::Batch& batch, const glm::vec3& color,
const render::ShapePipelinePointer& pipeline = _simpleOpaquePipeline) { const render::ShapePipelinePointer& pipeline = _simpleOpaquePipeline) {
renderSolidSphereInstance(batch, glm::vec4(color, 1.0f), pipeline); renderSolidSphereInstance(args, batch, glm::vec4(color, 1.0f), pipeline);
} }
void renderWireSphereInstance(gpu::Batch& batch, const glm::vec4& color, void renderWireSphereInstance(RenderArgs* args, gpu::Batch& batch, const glm::vec4& color,
const render::ShapePipelinePointer& pipeline = _simpleWirePipeline); const render::ShapePipelinePointer& pipeline = _simpleWirePipeline);
void renderWireSphereInstance(gpu::Batch& batch, const glm::vec3& color, void renderWireSphereInstance(RenderArgs* args, gpu::Batch& batch, const glm::vec3& color,
const render::ShapePipelinePointer& pipeline = _simpleWirePipeline) { const render::ShapePipelinePointer& pipeline = _simpleWirePipeline) {
renderWireSphereInstance(batch, glm::vec4(color, 1.0f), pipeline); renderWireSphereInstance(args, batch, glm::vec4(color, 1.0f), pipeline);
} }
void renderSolidCubeInstance(gpu::Batch& batch, const glm::vec4& color, void renderSolidCubeInstance(RenderArgs* args, gpu::Batch& batch, const glm::vec4& color,
const render::ShapePipelinePointer& pipeline = _simpleOpaquePipeline); const render::ShapePipelinePointer& pipeline = _simpleOpaquePipeline);
void renderSolidCubeInstance(gpu::Batch& batch, const glm::vec3& color, void renderSolidCubeInstance(RenderArgs* args, gpu::Batch& batch, const glm::vec3& color,
const render::ShapePipelinePointer& pipeline = _simpleOpaquePipeline) { const render::ShapePipelinePointer& pipeline = _simpleOpaquePipeline) {
renderSolidCubeInstance(batch, glm::vec4(color, 1.0f), pipeline); renderSolidCubeInstance(args, batch, glm::vec4(color, 1.0f), pipeline);
} }
void renderWireCubeInstance(gpu::Batch& batch, const glm::vec4& color, void renderWireCubeInstance(RenderArgs* args, gpu::Batch& batch, const glm::vec4& color,
const render::ShapePipelinePointer& pipeline = _simpleWirePipeline); const render::ShapePipelinePointer& pipeline = _simpleWirePipeline);
void renderWireCubeInstance(gpu::Batch& batch, const glm::vec3& color, void renderWireCubeInstance(RenderArgs* args, gpu::Batch& batch, const glm::vec3& color,
const render::ShapePipelinePointer& pipeline = _simpleWirePipeline) { const render::ShapePipelinePointer& pipeline = _simpleWirePipeline) {
renderWireCubeInstance(batch, glm::vec4(color, 1.0f), pipeline); renderWireCubeInstance(args, batch, glm::vec4(color, 1.0f), pipeline);
} }
// Dynamic geometry // Dynamic geometry

View file

@ -574,8 +574,8 @@ void LightClusteringPass::run(const render::RenderContextPointer& renderContext,
} }
// From the LightStage and the current frame, update the light cluster Grid // From the LightStage and the current frame, update the light cluster Grid
auto deferredLightingEffect = DependencyManager::get<DeferredLightingEffect>(); auto lightStage = renderContext->_scene->getStage<LightStage>();
auto lightStage = deferredLightingEffect->getLightStage(); assert(lightStage);
_lightClusters->updateLightStage(lightStage); _lightClusters->updateLightStage(lightStage);
_lightClusters->updateLightFrame(lightStage->_currentFrame, lightingModel->isPointLightEnabled(), lightingModel->isSpotLightEnabled()); _lightClusters->updateLightFrame(lightStage->_currentFrame, lightingModel->isPointLightEnabled(), lightingModel->isSpotLightEnabled());

View file

@ -55,7 +55,8 @@ LightPayload::~LightPayload() {
void LightPayload::render(RenderArgs* args) { void LightPayload::render(RenderArgs* args) {
if (!_stage) { if (!_stage) {
_stage = DependencyManager::get<DeferredLightingEffect>()->getLightStage(); _stage = args->_scene->getStage<LightStage>();
assert(_stage);
} }
// Do we need to allocate the light in the stage ? // Do we need to allocate the light in the stage ?
if (LightStage::isIndexInvalid(_index)) { if (LightStage::isIndexInvalid(_index)) {
@ -123,7 +124,8 @@ KeyLightPayload::~KeyLightPayload() {
void KeyLightPayload::render(RenderArgs* args) { void KeyLightPayload::render(RenderArgs* args) {
if (!_stage) { if (!_stage) {
_stage = DependencyManager::get<DeferredLightingEffect>()->getLightStage(); _stage = args->_scene->getStage<LightStage>();
assert(_stage);
} }
// Do we need to allocate the light in the stage ? // Do we need to allocate the light in the stage ?
if (LightStage::isIndexInvalid(_index)) { if (LightStage::isIndexInvalid(_index)) {

View file

@ -13,6 +13,11 @@
#include "LightStage.h" #include "LightStage.h"
std::string LightStage::_stageName { "LIGHT_STAGE"};
LightStage::LightStage() {
}
LightStage::Shadow::Shadow(model::LightPointer light) : _light{ light}, _frustum{ std::make_shared<ViewFrustum>() } { LightStage::Shadow::Shadow(model::LightPointer light) : _light{ light}, _frustum{ std::make_shared<ViewFrustum>() } {
framebuffer = gpu::FramebufferPointer(gpu::Framebuffer::createShadowmap(MAP_SIZE)); framebuffer = gpu::FramebufferPointer(gpu::Framebuffer::createShadowmap(MAP_SIZE));
map = framebuffer->getDepthStencilBuffer(); map = framebuffer->getDepthStencilBuffer();
@ -165,3 +170,14 @@ void LightStage::updateLightArrayBuffer(Index lightId) {
} }
} }
LightStageSetup::LightStageSetup() {
}
void LightStageSetup::run(const render::RenderContextPointer& renderContext) {
auto stage = renderContext->_scene->getStage(LightStage::getName());
if (!stage) {
stage = std::make_shared<LightStage>();
renderContext->_scene->resetStage(LightStage::getName(), stage);
}
}

View file

@ -14,17 +14,23 @@
#include <set> #include <set>
#include <unordered_map> #include <unordered_map>
#include <gpu/Framebuffer.h>
#include <model/Light.h>
#include <render/IndexedContainer.h> #include <render/IndexedContainer.h>
#include <render/Stage.h>
#include "gpu/Framebuffer.h" #include <render/Engine.h>
#include "model/Light.h"
class ViewFrustum; class ViewFrustum;
// Light stage to set up light-related rendering tasks // Light stage to set up light-related rendering tasks
class LightStage { class LightStage : public render::Stage {
public: public:
static std::string _stageName;
static const std::string& getName() { return _stageName; }
using Index = render::indexed_container::Index; using Index = render::indexed_container::Index;
static const Index INVALID_INDEX { render::indexed_container::INVALID_INDEX }; static const Index INVALID_INDEX { render::indexed_container::INVALID_INDEX };
static bool isIndexInvalid(Index index) { return index == INVALID_INDEX; } static bool isIndexInvalid(Index index) { return index == INVALID_INDEX; }
@ -93,6 +99,7 @@ public:
LightPointer getLight(Index lightId) const { LightPointer getLight(Index lightId) const {
return _lights.get(lightId); return _lights.get(lightId);
} }
Index getShadowId(Index lightId) const { Index getShadowId(Index lightId) const {
if (checkLightId(lightId)) { if (checkLightId(lightId)) {
return _descs[lightId].shadowId; return _descs[lightId].shadowId;
@ -109,6 +116,7 @@ public:
return LightAndShadow(getLight(lightId), getShadow(lightId)); return LightAndShadow(getLight(lightId), getShadow(lightId));
} }
LightStage();
Lights _lights; Lights _lights;
LightMap _lightMap; LightMap _lightMap;
Descs _descs; Descs _descs;
@ -149,5 +157,15 @@ using LightStagePointer = std::shared_ptr<LightStage>;
class LightStageSetup {
public:
using JobModel = render::Job::Model<LightStageSetup>;
LightStageSetup();
void run(const render::RenderContextPointer& renderContext);
protected:
};
#endif #endif

View file

@ -259,7 +259,7 @@ void MeshPartPayload::render(RenderArgs* args) {
gpu::Batch& batch = *(args->_batch); gpu::Batch& batch = *(args->_batch);
auto locations = args->_pipeline->locations; auto locations = args->_shapePipeline->locations;
assert(locations); assert(locations);
// Bind the model transform and the skinCLusterMatrices if needed // Bind the model transform and the skinCLusterMatrices if needed
@ -583,7 +583,7 @@ void ModelMeshPartPayload::render(RenderArgs* args) {
} }
gpu::Batch& batch = *(args->_batch); gpu::Batch& batch = *(args->_batch);
auto locations = args->_pipeline->locations; auto locations = args->_shapePipeline->locations;
assert(locations); assert(locations);
bindTransform(batch, locations, args->_renderMode); bindTransform(batch, locations, args->_renderMode);

View file

@ -76,8 +76,8 @@ void initForwardPipelines(ShapePlumber& plumber);
void addPlumberPipeline(ShapePlumber& plumber, void addPlumberPipeline(ShapePlumber& plumber,
const ShapeKey& key, const gpu::ShaderPointer& vertex, const gpu::ShaderPointer& pixel); const ShapeKey& key, const gpu::ShaderPointer& vertex, const gpu::ShaderPointer& pixel);
void batchSetter(const ShapePipeline& pipeline, gpu::Batch& batch); void batchSetter(const ShapePipeline& pipeline, gpu::Batch& batch, RenderArgs* args);
void lightBatchSetter(const ShapePipeline& pipeline, gpu::Batch& batch); void lightBatchSetter(const ShapePipeline& pipeline, gpu::Batch& batch, RenderArgs* args);
void initOverlay3DPipelines(ShapePlumber& plumber) { void initOverlay3DPipelines(ShapePlumber& plumber) {
auto vertex = gpu::Shader::createVertex(std::string(overlay3D_vert)); auto vertex = gpu::Shader::createVertex(std::string(overlay3D_vert));
@ -359,7 +359,7 @@ void addPlumberPipeline(ShapePlumber& plumber,
} }
} }
void batchSetter(const ShapePipeline& pipeline, gpu::Batch& batch) { void batchSetter(const ShapePipeline& pipeline, gpu::Batch& batch, RenderArgs* args) {
// Set a default albedo map // Set a default albedo map
batch.setResourceTexture(render::ShapePipeline::Slot::MAP::ALBEDO, batch.setResourceTexture(render::ShapePipeline::Slot::MAP::ALBEDO,
DependencyManager::get<TextureCache>()->getWhiteTexture()); DependencyManager::get<TextureCache>()->getWhiteTexture());
@ -382,13 +382,13 @@ void batchSetter(const ShapePipeline& pipeline, gpu::Batch& batch) {
} }
} }
void lightBatchSetter(const ShapePipeline& pipeline, gpu::Batch& batch) { void lightBatchSetter(const ShapePipeline& pipeline, gpu::Batch& batch, RenderArgs* args) {
// Set the batch // Set the batch
batchSetter(pipeline, batch); batchSetter(pipeline, batch, args);
// Set the light // Set the light
if (pipeline.locations->lightBufferUnit >= 0) { if (pipeline.locations->lightBufferUnit >= 0) {
DependencyManager::get<DeferredLightingEffect>()->setupKeyLightBatch(batch, DependencyManager::get<DeferredLightingEffect>()->setupKeyLightBatch(args, batch,
pipeline.locations->lightBufferUnit, pipeline.locations->lightBufferUnit,
pipeline.locations->lightAmbientBufferUnit, pipeline.locations->lightAmbientBufferUnit,
pipeline.locations->lightAmbientMapUnit); pipeline.locations->lightAmbientMapUnit);

View file

@ -35,8 +35,8 @@ void RenderShadowMap::run(const render::RenderContextPointer& renderContext,
assert(renderContext->args); assert(renderContext->args);
assert(renderContext->args->hasViewFrustum()); assert(renderContext->args->hasViewFrustum());
auto lightStage = DependencyManager::get<DeferredLightingEffect>()->getLightStage(); auto lightStage = renderContext->_scene->getStage<LightStage>();
assert(lightStage);
LightStage::Index globalLightIndex { 0 }; LightStage::Index globalLightIndex { 0 };
const auto globalLight = lightStage->getLight(globalLightIndex); const auto globalLight = lightStage->getLight(globalLightIndex);
@ -68,7 +68,7 @@ void RenderShadowMap::run(const render::RenderContextPointer& renderContext,
std::vector<ShapeKey> skinnedShapeKeys{}; std::vector<ShapeKey> skinnedShapeKeys{};
// Iterate through all inShapes and render the unskinned // Iterate through all inShapes and render the unskinned
args->_pipeline = shadowPipeline; args->_shapePipeline = shadowPipeline;
batch.setPipeline(shadowPipeline->pipeline); batch.setPipeline(shadowPipeline->pipeline);
for (auto items : inShapes) { for (auto items : inShapes) {
if (items.first.isSkinned()) { if (items.first.isSkinned()) {
@ -79,13 +79,13 @@ void RenderShadowMap::run(const render::RenderContextPointer& renderContext,
} }
// Reiterate to render the skinned // Reiterate to render the skinned
args->_pipeline = shadowSkinnedPipeline; args->_shapePipeline = shadowSkinnedPipeline;
batch.setPipeline(shadowSkinnedPipeline->pipeline); batch.setPipeline(shadowSkinnedPipeline->pipeline);
for (const auto& key : skinnedShapeKeys) { for (const auto& key : skinnedShapeKeys) {
renderItems(renderContext, inShapes.at(key)); renderItems(renderContext, inShapes.at(key));
} }
args->_pipeline = nullptr; args->_shapePipeline = nullptr;
args->_batch = nullptr; args->_batch = nullptr;
}); });
} }
@ -140,7 +140,8 @@ void RenderShadowTask::configure(const Config& configuration) {
} }
void RenderShadowSetup::run(const render::RenderContextPointer& renderContext, Output& output) { void RenderShadowSetup::run(const render::RenderContextPointer& renderContext, Output& output) {
auto lightStage = DependencyManager::get<DeferredLightingEffect>()->getLightStage(); auto lightStage = renderContext->_scene->getStage<LightStage>();
assert(lightStage);
const auto globalShadow = lightStage->getShadow(0); const auto globalShadow = lightStage->getShadow(0);
// Cache old render args // Cache old render args

View file

@ -532,9 +532,11 @@ void DebugSubsurfaceScattering::run(const render::RenderContextPointer& renderCo
auto lightStage = renderContext->_scene->getStage<LightStage>();
const auto light = DependencyManager::get<DeferredLightingEffect>()->getLightStage()->getLight(0); assert(lightStage);
// const auto light = DependencyManager::get<DeferredLightingEffect>()->getLightStage()->getLight(0);
const auto light = lightStage->getLight(0);
gpu::doInBatch(args->_context, [=](gpu::Batch& batch) { gpu::doInBatch(args->_context, [=](gpu::Batch& batch) {
batch.enableStereo(false); batch.enableStereo(false);

View file

@ -0,0 +1,26 @@
//
// UpdateSceneTask.cpp
// render-utils/src/
//
// Created by Sam Gateau on 6/21/2017.
// Copyright 2017 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 "UpdateSceneTask.h"
#include <render/SceneTask.h>
#include "LightStage.h"
#include "BackgroundStage.h"
#include "DeferredLightingEffect.h"
void UpdateSceneTask::build(JobModel& task, const render::Varying& input, render::Varying& output) {
task.addJob<LightStageSetup>("LightStageSetup");
task.addJob<BackgroundStageSetup>("BackgroundStageSetup");
task.addJob<DefaultLightingSetup>("DefaultLightingSetup");
task.addJob<render::PerformSceneTransaction>("PerformSceneTransaction");
}

View file

@ -0,0 +1,30 @@
//
// UpdateSceneTask.h
// render-utils/src/
//
// Created by Sam Gateau on 6/21/2017.
// Copyright 2017 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
//
#pragma once
#ifndef hifi_UpdateSceneTask_h
#define hifi_UpdateSceneTask_h
#include <render/Engine.h>
#include <render/RenderFetchCullSortTask.h>
class UpdateSceneTask {
public:
using JobModel = render::Task::Model<UpdateSceneTask>;
UpdateSceneTask() {}
void build(JobModel& task, const render::Varying& inputs, render::Varying& outputs);
};
#endif // hifi_UpdateSceneTask_h

View file

@ -52,13 +52,21 @@ void ZoneRendererTask::build(JobModel& task, const Varying& input, Varying& oupu
} }
void SetupZones::run(const RenderContextPointer& context, const Inputs& inputs) { void SetupZones::run(const RenderContextPointer& context, const Inputs& inputs) {
auto backgroundStage = context->_scene->getStage<BackgroundStage>();
auto backgroundStage = DependencyManager::get<DeferredLightingEffect>()->getBackgroundStage(); assert(backgroundStage);
backgroundStage->_currentFrame.clear(); backgroundStage->_currentFrame.clear();
// call render in the correct order first... // call render in the correct order first...
render::renderItems(context, inputs); render::renderItems(context, inputs);
// Finally add the default lights and background:
auto lightStage = context->_scene->getStage<LightStage>();
assert(lightStage);
lightStage->_currentFrame.pushSunLight(0);
lightStage->_currentFrame.pushAmbientLight(0);
backgroundStage->_currentFrame.pushBackground(0);
} }
const gpu::PipelinePointer& DebugZoneLighting::getKeyLightPipeline() { const gpu::PipelinePointer& DebugZoneLighting::getKeyLightPipeline() {
@ -130,14 +138,13 @@ void DebugZoneLighting::run(const render::RenderContextPointer& context, const I
auto deferredTransform = inputs; auto deferredTransform = inputs;
auto lightStage = DependencyManager::get<DeferredLightingEffect>()->getLightStage(); auto lightStage = context->_scene->getStage<LightStage>(LightStage::getName());
std::vector<model::LightPointer> keyLightStack; std::vector<model::LightPointer> keyLightStack;
if (lightStage && lightStage->_currentFrame._sunLights.size()) { if (lightStage && lightStage->_currentFrame._sunLights.size()) {
for (auto index : lightStage->_currentFrame._sunLights) { for (auto index : lightStage->_currentFrame._sunLights) {
keyLightStack.push_back(lightStage->getLight(index)); keyLightStack.push_back(lightStage->getLight(index));
} }
} }
keyLightStack.push_back(DependencyManager::get<DeferredLightingEffect>()->getGlobalLight());
std::vector<model::LightPointer> ambientLightStack; std::vector<model::LightPointer> ambientLightStack;
if (lightStage && lightStage->_currentFrame._ambientLights.size()) { if (lightStage && lightStage->_currentFrame._ambientLights.size()) {
@ -145,10 +152,8 @@ void DebugZoneLighting::run(const render::RenderContextPointer& context, const I
ambientLightStack.push_back(lightStage->getLight(index)); ambientLightStack.push_back(lightStage->getLight(index));
} }
} }
ambientLightStack.push_back(DependencyManager::get<DeferredLightingEffect>()->getGlobalLight());
auto backgroundStage = context->_scene->getStage<BackgroundStage>(BackgroundStage::getName());
auto backgroundStage = DependencyManager::get<DeferredLightingEffect>()->getBackgroundStage();
std::vector<model::SkyboxPointer> skyboxStack; std::vector<model::SkyboxPointer> skyboxStack;
if (backgroundStage && backgroundStage->_currentFrame._backgrounds.size()) { if (backgroundStage && backgroundStage->_currentFrame._backgrounds.size()) {
for (auto index : backgroundStage->_currentFrame._backgrounds) { for (auto index : backgroundStage->_currentFrame._backgrounds) {
@ -157,8 +162,7 @@ void DebugZoneLighting::run(const render::RenderContextPointer& context, const I
skyboxStack.push_back(background->getSkybox()); skyboxStack.push_back(background->getSkybox());
} }
} }
} }
skyboxStack.push_back(DependencyManager::get<DeferredLightingEffect>()->getDefaultSkybox());
gpu::doInBatch(args->_context, [=](gpu::Batch& batch) { gpu::doInBatch(args->_context, [=](gpu::Batch& batch) {

View file

@ -103,7 +103,7 @@ namespace render {
std::shared_ptr<gpu::Context> _context; std::shared_ptr<gpu::Context> _context;
std::shared_ptr<gpu::Framebuffer> _blitFramebuffer; std::shared_ptr<gpu::Framebuffer> _blitFramebuffer;
std::shared_ptr<render::ShapePipeline> _pipeline; std::shared_ptr<render::ShapePipeline> _shapePipeline;
QSharedPointer<QObject> _renderData; QSharedPointer<QObject> _renderData;
std::stack<ViewFrustum> _viewFrustums; std::stack<ViewFrustum> _viewFrustums;
glm::ivec4 _viewport { 0.0f, 0.0f, 1.0f, 1.0f }; glm::ivec4 _viewport { 0.0f, 0.0f, 1.0f, 1.0f };

View file

@ -43,11 +43,11 @@ void renderShape(RenderArgs* args, const ShapePlumberPointer& shapeContext, cons
assert(item.getKey().isShape()); assert(item.getKey().isShape());
auto key = item.getShapeKey() | globalKey; auto key = item.getShapeKey() | globalKey;
if (key.isValid() && !key.hasOwnPipeline()) { if (key.isValid() && !key.hasOwnPipeline()) {
args->_pipeline = shapeContext->pickPipeline(args, key); args->_shapePipeline = shapeContext->pickPipeline(args, key);
if (args->_pipeline) { if (args->_shapePipeline) {
item.render(args); item.render(args);
} }
args->_pipeline = nullptr; args->_shapePipeline = nullptr;
} else if (key.hasOwnPipeline()) { } else if (key.hasOwnPipeline()) {
item.render(args); item.render(args);
} else { } else {
@ -109,15 +109,15 @@ void render::renderStateSortShapes(const RenderContextPointer& renderContext,
// Then render // Then render
for (auto& pipelineKey : sortedPipelines) { for (auto& pipelineKey : sortedPipelines) {
auto& bucket = sortedShapes[pipelineKey]; auto& bucket = sortedShapes[pipelineKey];
args->_pipeline = shapeContext->pickPipeline(args, pipelineKey); args->_shapePipeline = shapeContext->pickPipeline(args, pipelineKey);
if (!args->_pipeline) { if (!args->_shapePipeline) {
continue; continue;
} }
for (auto& item : bucket) { for (auto& item : bucket) {
item.render(args); item.render(args);
} }
} }
args->_pipeline = nullptr; args->_shapePipeline = nullptr;
for (auto& item : ownPipelineBucket) { for (auto& item : ownPipelineBucket) {
item.render(args); item.render(args);
} }

View file

@ -18,6 +18,8 @@
#include <gpu/Context.h> #include <gpu/Context.h>
#include "EngineStats.h" #include "EngineStats.h"
#include "SceneTask.h"
#include "Logging.h" #include "Logging.h"
using namespace render; using namespace render;

View file

@ -237,3 +237,26 @@ void Scene::resetSelections(const Selections& selections) {
} }
} }
} }
// Access a particular Stage (empty if doesn't exist)
// Thread safe
StagePointer Scene::getStage(const Stage::Name& name) const {
std::unique_lock<std::mutex> lock(_stagesMutex);
auto found = _stages.find(name);
if (found == _stages.end()) {
return StagePointer();
} else {
return (*found).second;
}
}
void Scene::resetStage(const Stage::Name& name, const StagePointer& stage) {
std::unique_lock<std::mutex> lock(_stagesMutex);
auto found = _stages.find(name);
if (found == _stages.end()) {
_stages.insert(StageMap::value_type(name, stage));
} else {
(*found).second = stage;
}
}

View file

@ -14,6 +14,7 @@
#include "Item.h" #include "Item.h"
#include "SpatialTree.h" #include "SpatialTree.h"
#include "Stage.h"
#include "Selection.h" #include "Selection.h"
namespace render { namespace render {
@ -110,6 +111,19 @@ public:
// Access non-spatialized items (overlays, backgrounds) // Access non-spatialized items (overlays, backgrounds)
const ItemIDSet& getNonspatialSet() const { return _masterNonspatialSet; } const ItemIDSet& getNonspatialSet() const { return _masterNonspatialSet; }
// Access a particular Stage (empty if doesn't exist)
// Thread safe
StagePointer getStage(const Stage::Name& name) const;
template <class T>
std::shared_ptr<T> getStage(const Stage::Name& name = T::getName()) const {
auto stage = getStage(name);
return (stage ? std::static_pointer_cast<T>(stage) : std::shared_ptr<T>());
}
void resetStage(const Stage::Name& name, const StagePointer& stage);
protected: protected:
// Thread safe elements that can be accessed from anywhere // Thread safe elements that can be accessed from anywhere
std::atomic<unsigned int> _IDAllocator{ 1 }; // first valid itemID will be One std::atomic<unsigned int> _IDAllocator{ 1 }; // first valid itemID will be One
@ -128,7 +142,6 @@ protected:
void removeItems(const ItemIDs& ids); void removeItems(const ItemIDs& ids);
void updateItems(const ItemIDs& ids, UpdateFunctors& functors); void updateItems(const ItemIDs& ids, UpdateFunctors& functors);
// The Selection map // The Selection map
mutable std::mutex _selectionsMutex; // mutable so it can be used in the thread safe getSelection const method mutable std::mutex _selectionsMutex; // mutable so it can be used in the thread safe getSelection const method
SelectionMap _selections; SelectionMap _selections;
@ -139,6 +152,11 @@ protected:
// void appendToSelection(const Selection& selection); // void appendToSelection(const Selection& selection);
// void mergeWithSelection(const Selection& selection); // void mergeWithSelection(const Selection& selection);
// The Stage map
mutable std::mutex _stagesMutex; // mutable so it can be used in the thread safe getStage const method
StageMap _stages;
friend class Engine; friend class Engine;
}; };

View file

@ -0,0 +1,21 @@
//
// SceneTask.cpp
// render/src/render
//
// Created by Sam Gateau on 6/14/2017.
// Copyright 2017 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 "SceneTask.h"
using namespace render;
void PerformSceneTransaction::configure(const Config& config) {
}
void PerformSceneTransaction::run(const RenderContextPointer& renderContext) {
renderContext->_scene->processTransactionQueue();
}

View file

@ -0,0 +1,41 @@
//
// SceneTask.h
// render/src/render
//
// Created by Sam Gateau on 6/14/2017.
// Copyright 2017 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
//
#ifndef hifi_render_SceneTask_h
#define hifi_render_SceneTask_h
#include "Engine.h"
namespace render {
class PerformSceneTransactionConfig : public Job::Config {
Q_OBJECT
public:
signals:
void dirty();
protected:
};
class PerformSceneTransaction {
public:
using Config = PerformSceneTransactionConfig;
using JobModel = Job::Model<PerformSceneTransaction, Config>;
void configure(const Config& config);
void run(const RenderContextPointer& renderContext);
protected:
};
}
#endif // hifi_render_SceneTask_h

View file

@ -17,9 +17,9 @@
using namespace render; using namespace render;
void ShapePipeline::prepare(gpu::Batch& batch) { void ShapePipeline::prepare(gpu::Batch& batch, RenderArgs* args) {
if (batchSetter) { if (batchSetter) {
batchSetter(*this, batch); batchSetter(*this, batch, args);
} }
} }
@ -119,7 +119,7 @@ const ShapePipelinePointer ShapePlumber::pickPipeline(RenderArgs* args, const Ke
// Run the pipeline's BatchSetter on the passed in batch // Run the pipeline's BatchSetter on the passed in batch
if (shapePipeline->batchSetter) { if (shapePipeline->batchSetter) {
shapePipeline->batchSetter(*shapePipeline, *batch); shapePipeline->batchSetter(*shapePipeline, *batch, args);
} }
return shapePipeline; return shapePipeline;

View file

@ -240,14 +240,14 @@ public:
}; };
using LocationsPointer = std::shared_ptr<Locations>; using LocationsPointer = std::shared_ptr<Locations>;
using BatchSetter = std::function<void(const ShapePipeline&, gpu::Batch&)>; using BatchSetter = std::function<void(const ShapePipeline&, gpu::Batch&, RenderArgs* args)>;
ShapePipeline(gpu::PipelinePointer pipeline, LocationsPointer locations, BatchSetter batchSetter) : ShapePipeline(gpu::PipelinePointer pipeline, LocationsPointer locations, BatchSetter batchSetter) :
pipeline(pipeline), locations(locations), batchSetter(batchSetter) {} pipeline(pipeline), locations(locations), batchSetter(batchSetter) {}
// Normally, a pipeline is accessed thorugh pickPipeline. If it needs to be set manually, // Normally, a pipeline is accessed thorugh pickPipeline. If it needs to be set manually,
// after calling setPipeline this method should be called to prepare the pipeline with default buffers. // after calling setPipeline this method should be called to prepare the pipeline with default buffers.
void prepare(gpu::Batch& batch); void prepare(gpu::Batch& batch, RenderArgs* args);
gpu::PipelinePointer pipeline; gpu::PipelinePointer pipeline;
std::shared_ptr<Locations> locations; std::shared_ptr<Locations> locations;

View file

@ -0,0 +1,26 @@
//
// Stage.cpp
// render/src/render
//
// Created by Sam Gateau on 6/14/2017.
// Copyright 2017 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 "Stage.h"
using namespace render;
Stage::~Stage() {
}
Stage::Stage() :
_name()
{
}

View file

@ -0,0 +1,38 @@
//
// Stage.h
// render/src/render
//
// Created by Sam Gateau on 6/14/2017.
// Copyright 2017 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
//
#ifndef hifi_render_Stage_h
#define hifi_render_Stage_h
#include <memory>
#include <map>
#include <string>
namespace render {
class Stage {
public:
using Name = std::string;
Stage();
virtual ~Stage();
protected:
Name _name;
};
using StagePointer = std::shared_ptr<Stage>;
using StageMap = std::map<const Stage::Name, StagePointer>;
}
#endif // hifi_render_Stage_h

View file

@ -831,7 +831,9 @@ bool OffscreenQmlSurface::eventFilter(QObject* originalDestination, QEvent* even
mouseEvent->screenPos(), mouseEvent->button(), mouseEvent->screenPos(), mouseEvent->button(),
mouseEvent->buttons(), mouseEvent->modifiers()); mouseEvent->buttons(), mouseEvent->modifiers());
if (event->type() == QEvent::MouseMove) { if (event->type() == QEvent::MouseMove) {
_qmlContext->setContextProperty("lastMousePosition", transformedPos); // TODO - this line necessary for the QML Tooltop to work (which is not currently being used), but it causes interface to crash on launch on a fresh install
// need to investigate into why this crash is happening.
//_qmlContext->setContextProperty("lastMousePosition", transformedPos);
} }
mappedEvent.ignore(); mappedEvent.ignore();
if (QCoreApplication::sendEvent(_quickWindow, &mappedEvent)) { if (QCoreApplication::sendEvent(_quickWindow, &mappedEvent)) {

View file

@ -14,7 +14,8 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// //
/* global MyAvatar, Entities, Script, Camera, Vec3, Reticle, Overlays, getEntityCustomData, Messages, Quat, Controller */ /* global MyAvatar, Entities, Script, Camera, Vec3, Reticle, Overlays, getEntityCustomData, Messages, Quat, Controller,
isInEditMode, HMD */
(function() { // BEGIN LOCAL_SCOPE (function() { // BEGIN LOCAL_SCOPE
@ -22,6 +23,8 @@
Script.include("/~/system/libraries/utils.js"); Script.include("/~/system/libraries/utils.js");
var MAX_SOLID_ANGLE = 0.01; // objects that appear smaller than this can't be grabbed var MAX_SOLID_ANGLE = 0.01; // objects that appear smaller than this can't be grabbed
var DELAY_FOR_30HZ = 33; // milliseconds
var ZERO_VEC3 = { var ZERO_VEC3 = {
x: 0, x: 0,
y: 0, y: 0,
@ -46,7 +49,7 @@ var ACTION_TTL = 10; // seconds
function getTag() { function getTag() {
return "grab-" + MyAvatar.sessionUUID; return "grab-" + MyAvatar.sessionUUID;
} }
var DISTANCE_HOLDING_ACTION_TIMEFRAME = 0.1; // how quickly objects move to their new position var DISTANCE_HOLDING_ACTION_TIMEFRAME = 0.1; // how quickly objects move to their new position
var DISTANCE_HOLDING_UNITY_MASS = 1200; // The mass at which the distance holding action timeframe is unmodified var DISTANCE_HOLDING_UNITY_MASS = 1200; // The mass at which the distance holding action timeframe is unmodified
var DISTANCE_HOLDING_UNITY_DISTANCE = 6; // The distance at which the distance holding action timeframe is unmodified var DISTANCE_HOLDING_UNITY_DISTANCE = 6; // The distance at which the distance holding action timeframe is unmodified
@ -411,10 +414,15 @@ Grabber.prototype.pressEvent = function(event) {
}; };
Grabber.prototype.releaseEvent = function(event) { Grabber.prototype.releaseEvent = function(event) {
if (event.isLeftButton!==true ||event.isRightButton===true || event.isMiddleButton===true) { if (event.isLeftButton!==true || event.isRightButton===true || event.isMiddleButton===true) {
return; return;
} }
if (this.moveEventTimer) {
Script.clearTimeout(this.moveEventTimer);
this.moveEventTimer = null;
}
if (this.isGrabbing) { if (this.isGrabbing) {
// this.deactivateEntity(this.entityID); // this.deactivateEntity(this.entityID);
this.isGrabbing = false; this.isGrabbing = false;
@ -439,12 +447,28 @@ Grabber.prototype.releaseEvent = function(event) {
} }
}; };
Grabber.prototype.scheduleMouseMoveProcessor = function(event) {
var _this = this;
if (!this.moveEventTimer) {
this.moveEventTimer = Script.setTimeout(function() {
_this.moveEventProcess();
}, DELAY_FOR_30HZ);
}
};
Grabber.prototype.moveEvent = function(event) { Grabber.prototype.moveEvent = function(event) {
// during the handling of the event, do as little as possible. We save the updated mouse position,
// and start a timer to react to the change. If more changes arrive before the timer fires, only
// the last update will be considered. This is done to avoid backing-up Qt's event queue.
if (!this.isGrabbing) { if (!this.isGrabbing) {
return; return;
} }
mouse.updateDrag(event); mouse.updateDrag(event);
this.scheduleMouseMoveProcessor();
};
Grabber.prototype.moveEventProcess = function() {
this.moveEventTimer = null;
// see if something added/restored gravity // see if something added/restored gravity
var entityProperties = Entities.getEntityProperties(this.entityID); var entityProperties = Entities.getEntityProperties(this.entityID);
if (!entityProperties || !entityProperties.gravity) { if (!entityProperties || !entityProperties.gravity) {
@ -489,7 +513,7 @@ Grabber.prototype.moveEvent = function(event) {
} else { } else {
var newPointOnPlane; var newPointOnPlane;
if (this.mode === "verticalCylinder") { if (this.mode === "verticalCylinder") {
// for this mode we recompute the plane based on current Camera // for this mode we recompute the plane based on current Camera
var planeNormal = Quat.getForward(Camera.getOrientation()); var planeNormal = Quat.getForward(Camera.getOrientation());
@ -505,7 +529,7 @@ Grabber.prototype.moveEvent = function(event) {
}; };
} else { } else {
newPointOnPlane = mouseIntersectionWithPlane( newPointOnPlane = mouseIntersectionWithPlane(
this.pointOnPlane, this.planeNormal, mouse.current, this.maxDistance); this.pointOnPlane, this.planeNormal, mouse.current, this.maxDistance);
var relativePosition = Vec3.subtract(newPointOnPlane, cameraPosition); var relativePosition = Vec3.subtract(newPointOnPlane, cameraPosition);
@ -538,6 +562,8 @@ Grabber.prototype.moveEvent = function(event) {
} else { } else {
Entities.updateAction(this.entityID, this.actionID, actionArgs); Entities.updateAction(this.entityID, this.actionID, actionArgs);
} }
this.scheduleMouseMoveProcessor();
}; };
Grabber.prototype.keyReleaseEvent = function(event) { Grabber.prototype.keyReleaseEvent = function(event) {

View file

@ -14,8 +14,6 @@ Script.include(Script.resolvePath("../libraries/utils.js"));
Script.include(Script.resolvePath("../libraries/controllers.js")); Script.include(Script.resolvePath("../libraries/controllers.js"));
Script.include(Script.resolvePath("../libraries/Xform.js")); Script.include(Script.resolvePath("../libraries/Xform.js"));
var VEC3_ZERO = {x: 0, y: 0, z: 0};
var X_AXIS = {x: 1, y: 0, z: 0};
var Y_AXIS = {x: 0, y: 1, z: 0}; var Y_AXIS = {x: 0, y: 1, z: 0};
var DEFAULT_DPI = 34; var DEFAULT_DPI = 34;
var DEFAULT_WIDTH = 0.4375; var DEFAULT_WIDTH = 0.4375;
@ -25,12 +23,13 @@ var CAMERA_MATRIX = -7;
var ROT_Y_180 = {x: 0.0, y: 1.0, z: 0, w: 0}; var ROT_Y_180 = {x: 0.0, y: 1.0, z: 0, w: 0};
var ROT_LANDSCAPE = {x: 1.0, y: 1.0, z: 0, w: 0}; var ROT_LANDSCAPE = {x: 1.0, y: 1.0, z: 0, w: 0};
var ROT_LANDSCAPE_WINDOW = {x: 0.0, y: 0.0, z: 0.0, w: 0}; var ROT_LANDSCAPE_WINDOW = {x: 0.0, y: 0.0, z: 0.0, w: 0};
var ROT_IDENT = {x: 0, y: 0, z: 0, w: 1};
var TABLET_TEXTURE_RESOLUTION = { x: 480, y: 706 }; var TABLET_TEXTURE_RESOLUTION = { x: 480, y: 706 };
var INCHES_TO_METERS = 1 / 39.3701; var INCHES_TO_METERS = 1 / 39.3701;
var AVATAR_SELF_ID = "{00000000-0000-0000-0000-000000000001}"; var AVATAR_SELF_ID = "{00000000-0000-0000-0000-000000000001}";
var NO_HANDS = -1; var NO_HANDS = -1;
var DELAY_FOR_30HZ = 33; // milliseconds
// will need to be recaclulated if dimensions of fbx model change. // will need to be recaclulated if dimensions of fbx model change.
var TABLET_NATURAL_DIMENSIONS = {x: 33.797, y: 50.129, z: 2.269}; var TABLET_NATURAL_DIMENSIONS = {x: 33.797, y: 50.129, z: 2.269};
@ -561,9 +560,29 @@ function rayIntersectPlane(planePosition, planeNormal, rayStart, rayDirection) {
} }
} }
WebTablet.prototype.scheduleMouseMoveProcessor = function() {
var _this = this;
if (!this.moveEventTimer) {
this.moveEventTimer = Script.setTimeout(function() {
_this.mouseMoveProcessor();
}, DELAY_FOR_30HZ);
}
};
WebTablet.prototype.mouseMoveEvent = function (event) { WebTablet.prototype.mouseMoveEvent = function (event) {
if (this.dragging) { if (this.dragging) {
var pickRay = Camera.computePickRay(event.x, event.y); this.currentMouse = {
x: event.x,
y: event.y
};
this.scheduleMouseMoveProcessor();
}
};
WebTablet.prototype.mouseMoveProcessor = function () {
this.moveEventTimer = null;
if (this.dragging) {
var pickRay = Camera.computePickRay(this.currentMouse.x, this.currentMouse.y);
// transform pickRay into camera local coordinates // transform pickRay into camera local coordinates
var invCameraXform = new Xform(Camera.orientation, Camera.position).inv(); var invCameraXform = new Xform(Camera.orientation, Camera.position).inv();
@ -582,6 +601,7 @@ WebTablet.prototype.mouseMoveEvent = function (event) {
localPosition: localPosition localPosition: localPosition
}); });
} }
this.scheduleMouseMoveProcessor();
} }
}; };

View file

@ -77,7 +77,6 @@ void TestWindow::initGl() {
#ifdef DEFERRED_LIGHTING #ifdef DEFERRED_LIGHTING
auto deferredLightingEffect = DependencyManager::get<DeferredLightingEffect>(); auto deferredLightingEffect = DependencyManager::get<DeferredLightingEffect>();
deferredLightingEffect->init(); deferredLightingEffect->init();
deferredLightingEffect->setGlobalLight(_light);
initDeferredPipelines(*_shapePlumber); initDeferredPipelines(*_shapePlumber);
#endif #endif
} }

View file

@ -889,11 +889,6 @@ private:
BackgroundRenderData::_item = _main3DScene->allocateID(); BackgroundRenderData::_item = _main3DScene->allocateID();
transaction.resetItem(BackgroundRenderData::_item, backgroundRenderPayload); transaction.resetItem(BackgroundRenderData::_item, backgroundRenderPayload);
} }
// Setup the current Zone Entity lighting
{
auto stage = DependencyManager::get<SceneScriptingInterface>()->getSkyStage();
DependencyManager::get<DeferredLightingEffect>()->setGlobalLight(stage->getSunLight());
}
{ {
PerformanceTimer perfTimer("SceneProcessTransaction"); PerformanceTimer perfTimer("SceneProcessTransaction");
@ -914,8 +909,6 @@ private:
PerformanceTimer perfTimer("draw"); PerformanceTimer perfTimer("draw");
// The pending changes collecting the changes here // The pending changes collecting the changes here
render::Transaction transaction; render::Transaction transaction;
// Setup the current Zone Entity lighting
DependencyManager::get<DeferredLightingEffect>()->setGlobalLight(_sunSkyStage.getSunLight());
{ {
PerformanceTimer perfTimer("SceneProcessTransaction"); PerformanceTimer perfTimer("SceneProcessTransaction");
_main3DScene->enqueueTransaction(transaction); _main3DScene->enqueueTransaction(transaction);

View file

@ -0,0 +1,107 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="140mm"
height="140mm"
viewBox="0 0 140 140"
version="1.1"
id="svg8"
inkscape:version="0.92.1 r15371"
sodipodi:docname="laser-a.svg">
<defs
id="defs2" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="1"
inkscape:pageshadow="2"
inkscape:zoom="0.35"
inkscape:cx="1038.9217"
inkscape:cy="879.1901"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"
objecttolerance="3"
inkscape:window-width="2194"
inkscape:window-height="1171"
inkscape:window-x="2186"
inkscape:window-y="-8"
inkscape:window-maximized="1"
inkscape:pagecheckerboard="true" />
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-157)">
<circle
id="path3680"
cx="53.672615"
cy="245.59525"
r="20.410715"
style="stroke-width:0.26458332;fill:#000000;stroke:#000000;stroke-opacity:1" />
<path
sodipodi:type="star"
id="path3684"
sodipodi:sides="5"
sodipodi:cx="48.380951"
sodipodi:cy="175.29166"
sodipodi:r1="47.150944"
sodipodi:r2="13.598276"
sodipodi:arg1="1.0897856"
sodipodi:arg2="1.6872054"
inkscape:flatsided="false"
inkscape:rounded="0"
inkscape:randomized="0"
d="M 70.196535,217.09228 46.801561,188.7979 15.367586,208.95661 35.047691,177.96323 6.161985,154.29712 l 35.557948,9.13941 13.581627,-34.78516 2.295916,36.64185 37.279613,2.16768 -34.138995,13.5065 z"
inkscape:transform-center-x="1.9762951"
inkscape:transform-center-y="1.2684232"
style="stroke-width:0.26458332;fill:#000000;stroke:#000000;stroke-opacity:1"
transform="matrix(0.75680215,0,0,0.80599932,17.17868,104.2376)" />
<path
sodipodi:type="star"
id="path3694"
sodipodi:sides="5"
sodipodi:cx="53.381914"
sodipodi:cy="244.31365"
sodipodi:r1="48.628967"
sodipodi:r2="10.608823"
sodipodi:arg1="1.7183633"
sodipodi:arg2="2.3466818"
inkscape:flatsided="false"
inkscape:rounded="0"
inkscape:randomized="0"
d="M 46.231899,292.4141 45.95204,251.88623 5.4261854,252.37744 43.883994,239.58748 30.893657,201.19689 54.941748,233.82012 87.439133,209.60223 63.843862,242.55446 96.918688,265.97757 58.287917,253.71993 Z"
inkscape:transform-center-x="3.6110896"
inkscape:transform-center-y="0.36477657"
style="stroke-width:0.26458332;fill:#000000;stroke:#000000;stroke-opacity:1" />
<path
style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:7.708;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 56.694008,239.30541 135.65246,167.44572"
id="path3702"
inkscape:connector-curvature="0"
inkscape:transform-center-x="-1.5119048"
inkscape:transform-center-y="23.434524" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.8 KiB

View file

@ -0,0 +1,106 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="140mm"
height="140mm"
viewBox="0 0 140 140"
version="1.1"
id="svg8"
inkscape:version="0.92.1 r15371"
sodipodi:docname="laser.svg">
<defs
id="defs2" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.35"
inkscape:cx="1523.2074"
inkscape:cy="879.1901"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"
objecttolerance="3"
inkscape:window-width="2194"
inkscape:window-height="1171"
inkscape:window-x="-8"
inkscape:window-y="-8"
inkscape:window-maximized="1" />
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-157)">
<circle
id="path3680"
cx="53.672615"
cy="245.59525"
r="20.410715"
style="stroke-width:0.26458332;fill:#ffffff;stroke:#ffffff;stroke-opacity:1" />
<path
sodipodi:type="star"
id="path3684"
sodipodi:sides="5"
sodipodi:cx="48.380951"
sodipodi:cy="175.29166"
sodipodi:r1="47.150944"
sodipodi:r2="13.598276"
sodipodi:arg1="1.0897856"
sodipodi:arg2="1.6872054"
inkscape:flatsided="false"
inkscape:rounded="0"
inkscape:randomized="0"
d="M 70.196535,217.09228 46.801561,188.7979 15.367586,208.95661 35.047691,177.96323 6.161985,154.29712 l 35.557948,9.13941 13.581627,-34.78516 2.295916,36.64185 37.279613,2.16768 -34.138995,13.5065 z"
inkscape:transform-center-x="1.9762951"
inkscape:transform-center-y="1.2684232"
style="stroke-width:0.26458332;fill:#ffffff;stroke:#ffffff;stroke-opacity:1"
transform="matrix(0.75680215,0,0,0.80599932,17.17868,104.2376)" />
<path
sodipodi:type="star"
id="path3694"
sodipodi:sides="5"
sodipodi:cx="53.381914"
sodipodi:cy="244.31365"
sodipodi:r1="48.628967"
sodipodi:r2="10.608823"
sodipodi:arg1="1.7183633"
sodipodi:arg2="2.3466818"
inkscape:flatsided="false"
inkscape:rounded="0"
inkscape:randomized="0"
d="M 46.231899,292.4141 45.95204,251.88623 5.4261854,252.37744 43.883994,239.58748 30.893657,201.19689 54.941748,233.82012 87.439133,209.60223 63.843862,242.55446 96.918688,265.97757 58.287917,253.71993 Z"
inkscape:transform-center-x="3.6110896"
inkscape:transform-center-y="0.36477657"
style="stroke-width:0.26458332;fill:#ffffff;stroke:#ffffff;stroke-opacity:1" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:7.70800018;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 56.694008,239.30541 135.65246,167.44572"
id="path3702"
inkscape:connector-curvature="0"
inkscape:transform-center-x="-1.5119048"
inkscape:transform-center-y="23.434524" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.7 KiB

View file

@ -0,0 +1,274 @@
//
// Created by Alan-Michael Moody on 6/4/2017
//
'use strict';
(function () {
Script.include("/~/system/libraries/controllers.js");
var APP_NAME = 'LASER',
APP_ICON = Script.resolvePath('laser.svg'),
APP_ICON_ACTIVE = Script.resolvePath('laser-a.svg');
var POINT_INDEX_CHANNEL = "Hifi-Point-Index",
GRAB_DISABLE_CHANNEL = "Hifi-Grab-Disable",
POINTER_DISABLE_CHANNEL = "Hifi-Pointer-Disable";
var TRIGGER_PRESSURE = 0.95;
var tablet = Tablet.getTablet('com.highfidelity.interface.tablet.system');
var button = tablet.addButton({
icon: APP_ICON,
activeIcon: APP_ICON_ACTIVE,
text: APP_NAME
});
var laserEntities = {
left: {
beam: null,
sphere: null
},
right: {
beam: null,
sphere: null
}
};
var rayExclusionList = [];
function laser(hand) {
var PICK_MAX_DISTANCE = 500;
var FORWARD_OFFSET = 0.05;
var isNewEntityNeeded = (laserEntities[hand].beam === null);
var jointName = hand === 'right' ? 'RightHandIndex4' : 'LeftHandIndex4'; //'RightHand' : 'LeftHand';
var _hand = hand === 'right' ? Controller.Standard.RightHand : Controller.Standard.LeftHand;
var controllerLocation = getControllerWorldLocation(_hand, true);
var worldControllerPosition = controllerLocation.position;
var worldControllerRotation = controllerLocation.orientation;
var jointExists = (MyAvatar.getJointIndex(jointName) > 0) ;
var CONTROLLER_FORWARD_OFFSET = Vec3.multiply(Quat.getUp(worldControllerRotation), FORWARD_OFFSET);
var pickRay = {
origin: worldControllerPosition,
direction: Quat.getUp(worldControllerRotation),
length: PICK_MAX_DISTANCE
};
if (jointExists) {
pickRay.origin = MyAvatar.getJointPosition(jointName);
pickRay.direction = MyAvatar.jointToWorldDirection(Vec3.UP, MyAvatar.getJointIndex(jointName));
}
var ray = Entities.findRayIntersection(pickRay, true, [], rayExclusionList, true);
var avatarRay = AvatarManager.findRayIntersection(pickRay, true, [], rayExclusionList, true);
var dist = PICK_MAX_DISTANCE;
var intersection = null;
if (avatarRay.intersects) {
intersection = avatarRay.intersection;
dist = Vec3.distance(pickRay.origin, avatarRay.intersection);
} else if (ray.intersects) {
intersection = ray.intersection;
dist = Vec3.distance(pickRay.origin, ray.intersection);
}
var sphereSize = dist * 0.01;
if (isNewEntityNeeded) {
var sphere = {
lifetime: 360,
type: 'Sphere',
dimensions: {x: sphereSize, y: sphereSize, z: sphereSize},
color: {red: 0, green: 255, blue: 0},
position: intersection,
collisionless: true,
visible: false
};
var beam = {
lifetime: 360,
type: 'Line',
glow: 1.0,
lineWidth: 5,
alpha: 0.5,
ignoreRayIntersection: true,
drawInFront: true,
color: {red: 0, green: 255, blue: 0},
parentID: MyAvatar.sessionUUID,
dimensions: Vec3.multiply(PICK_MAX_DISTANCE * 2, Vec3.ONE),
linePoints: [Vec3.ZERO, {x: 0, y: dist - FORWARD_OFFSET, z: 0}]
};
if(jointExists) {
beam.parentJointIndex = MyAvatar.getJointIndex(jointName);
beam.localPosition = {x: 0, y: FORWARD_OFFSET, z: 0};
beam.localRotation = Quat.normalize({});
} else {
beam.position = Vec3.sum(pickRay.origin, CONTROLLER_FORWARD_OFFSET);
beam.rotation = worldControllerRotation;
}
laserEntities[hand].beam = Entities.addEntity(beam,true);
rayExclusionList.push(laserEntities[hand].beam);
laserEntities[hand].sphere = Entities.addEntity(sphere,true);
rayExclusionList.push(laserEntities[hand].sphere);
if (ray.intersects || avatarRay.intersects) {
Entities.editEntity(laserEntities[hand].sphere, {
visible: true
});
}
} else {
if (ray.intersects || avatarRay.intersects) {
if(jointExists) {
Entities.editEntity(laserEntities[hand].beam, {
parentID: MyAvatar.sessionUUID,
parentJointIndex: MyAvatar.getJointIndex(jointName),
localPosition: {x: 0, y: FORWARD_OFFSET, z: 0},
localRotation: Quat.normalize({}),
dimensions: Vec3.multiply(PICK_MAX_DISTANCE * 2, Vec3.ONE),
linePoints: [Vec3.ZERO, {x: 0, y: dist - FORWARD_OFFSET, z: 0}]
});
} else {
Entities.editEntity(laserEntities[hand].beam, {
parentID: MyAvatar.sessionUUID,
parentJointIndex: MyAvatar.getJointIndex(jointName),
position: Vec3.sum(pickRay.origin, CONTROLLER_FORWARD_OFFSET),
rotation: worldControllerRotation,
dimensions: Vec3.multiply(PICK_MAX_DISTANCE * 2, Vec3.ONE),
linePoints: [Vec3.ZERO, {x: 0, y: dist - FORWARD_OFFSET, z: 0}]
});
}
Entities.editEntity(laserEntities[hand].sphere, {
dimensions: {x: sphereSize, y: sphereSize, z: sphereSize},
position: intersection,
visible: true
});
} else {
if(jointExists) {
Entities.editEntity(laserEntities[hand].beam, {
parentID: MyAvatar.sessionUUID,
parentJointIndex: MyAvatar.getJointIndex(jointName),
localPosition: {x: 0, y: FORWARD_OFFSET, z: 0},
localRotation: Quat.normalize({}),
dimensions: Vec3.multiply(PICK_MAX_DISTANCE * 2, Vec3.ONE),
linePoints: [Vec3.ZERO, {x: 0, y: dist - FORWARD_OFFSET, z: 0}]
});
} else {
Entities.editEntity(laserEntities[hand].beam, {
parentID: MyAvatar.sessionUUID,
parentJointIndex: MyAvatar.getJointIndex(jointName),
position: Vec3.sum(pickRay.origin, CONTROLLER_FORWARD_OFFSET),
rotation: worldControllerRotation,
dimensions: Vec3.multiply(PICK_MAX_DISTANCE * 2, Vec3.ONE),
linePoints: [Vec3.ZERO, {x: 0, y: dist - FORWARD_OFFSET, z: 0}]
});
}
Entities.editEntity(laserEntities[hand].sphere, {
visible: false
});
}
}
}
function triggerWatcher(deltaTime) {
var deleteBeamLeft = true,
deleteBeamRight = true;
if (Controller.getValue(Controller.Standard.LT) > TRIGGER_PRESSURE) {
deleteBeamLeft = false;
laser('left');
}
if (Controller.getValue(Controller.Standard.RT) > TRIGGER_PRESSURE) {
deleteBeamRight = false;
laser('right');
}
if (deleteBeamLeft && laserEntities.left.beam !== null) {
Entities.deleteEntity(laserEntities.left.beam);
Entities.deleteEntity(laserEntities.left.sphere);
laserEntities.left.beam = null;
laserEntities.left.sphere = null;
}
if (deleteBeamRight && laserEntities.right.beam !== null) {
Entities.deleteEntity(laserEntities.right.beam);
Entities.deleteEntity(laserEntities.right.sphere);
laserEntities.right.beam = null;
laserEntities.right.sphere = null;
}
if (deleteBeamRight && deleteBeamLeft) {
rayExclusionList = [];
}
}
function selectionBeamSwitch(bool) {
Messages.sendMessage(GRAB_DISABLE_CHANNEL, JSON.stringify({
holdEnabled: bool,
nearGrabEnabled: bool,
farGrabEnabled: bool
}), true);
Messages.sendMessage(POINTER_DISABLE_CHANNEL, JSON.stringify({
pointerEnabled: bool
}), true);
Messages.sendMessage(POINT_INDEX_CHANNEL, JSON.stringify({
pointIndex: !bool
}), true);
}
var _switch = true;
function buttonSwitch() {
if (_switch) {
Script.update.connect(triggerWatcher);
Messages.subscribe(POINT_INDEX_CHANNEL);
Messages.subscribe(GRAB_DISABLE_CHANNEL);
Messages.subscribe(POINTER_DISABLE_CHANNEL);
} else {
Script.update.disconnect(triggerWatcher);
Messages.unsubscribe(POINT_INDEX_CHANNEL);
Messages.unsubscribe(GRAB_DISABLE_CHANNEL);
Messages.unsubscribe(POINTER_DISABLE_CHANNEL);
}
button.editProperties({isActive: _switch});
selectionBeamSwitch(!_switch);
_switch = !_switch;
}
button.clicked.connect(buttonSwitch);
function clean() {
tablet.removeButton(button);
Script.update.disconnect(triggerWatcher);
Messages.unsubscribe(POINT_INDEX_CHANNEL);
Messages.unsubscribe(GRAB_DISABLE_CHANNEL);
Messages.unsubscribe(POINTER_DISABLE_CHANNEL);
rayExclusionList = [];
}
Script.scriptEnding.connect(clean);
}());