diff --git a/libraries/entities-renderer/src/RenderableLightEntityItem.cpp b/libraries/entities-renderer/src/RenderableLightEntityItem.cpp index b7f32cca65..3264ecb077 100644 --- a/libraries/entities-renderer/src/RenderableLightEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableLightEntityItem.cpp @@ -25,31 +25,70 @@ EntityItemPointer RenderableLightEntityItem::factory(const EntityItemID& entityI return entity; } +RenderableLightEntityItem::RenderableLightEntityItem(const EntityItemID& entityItemID) : LightEntityItem(entityItemID), + _light(std::make_shared()), + _lightStamp(-1) +{ +} + +namespace render { + template <> const ItemKey payloadGetKey(const LightPayload::Pointer& payload) { + return ItemKey::Builder::light(); + } + + template <> const Item::Bound payloadGetBound(const LightPayload::Pointer& payload) { + if (payload) { + return payload->_bound; + } + return render::Item::Bound(); + } + template <> void payloadRender(const LightPayload::Pointer& payload, RenderArgs* args) { + if (args) { + if (payload) { + payload->render(args); + } + } + } +} + +void RenderableLightEntityItem::updateLightFromEntity() { + _light->setPosition(getPosition()); + _light->setOrientation(getRotation()); + + glm::vec3 dimensions = getDimensions(); + float largestDiameter = glm::max(dimensions.x, dimensions.y, dimensions.z); + _light->setMaximumRadius(largestDiameter / 2.0f); + + _light->setColor(toGlm(getXColor())); + + float intensity = getIntensity() * (_isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) : 1.0f); + _light->setIntensity(intensity); + + _light->setFalloffRadius(getFalloffRadius()); + + + float exponent = getExponent(); + float cutoff = glm::radians(getCutoff()); + if (!_isSpotlight) { + _light->setType(model::Light::POINT); + } else { + _light->setType(model::Light::SPOT); + + _light->setSpotAngle(cutoff); + _light->setSpotExponent(exponent); + } +} + void RenderableLightEntityItem::render(RenderArgs* args) { PerformanceTimer perfTimer("RenderableLightEntityItem::render"); assert(getType() == EntityTypes::Light); checkFading(); - glm::vec3 position = getPosition(); - glm::vec3 dimensions = getDimensions(); - glm::quat rotation = getRotation(); - float largestDiameter = glm::max(dimensions.x, dimensions.y, dimensions.z); - glm::vec3 color = toGlm(getXColor()); + updateLightFromEntity(); - float intensity = getIntensity() * (_isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) : 1.0f); - float falloffRadius = getFalloffRadius(); - float exponent = getExponent(); - float cutoff = glm::radians(getCutoff()); + DependencyManager::get()->addLight(_light); - if (_isSpotlight) { - DependencyManager::get()->addSpotLight(position, largestDiameter / 2.0f, - color, intensity, falloffRadius, rotation, exponent, cutoff); - } else { - DependencyManager::get()->addPointLight(position, largestDiameter / 2.0f, - color, intensity, falloffRadius); - } - #ifdef WANT_DEBUG Q_ASSERT(args->_batch); gpu::Batch& batch = *args->_batch; diff --git a/libraries/entities-renderer/src/RenderableLightEntityItem.h b/libraries/entities-renderer/src/RenderableLightEntityItem.h index 2db913db0d..c6e6aa7216 100644 --- a/libraries/entities-renderer/src/RenderableLightEntityItem.h +++ b/libraries/entities-renderer/src/RenderableLightEntityItem.h @@ -13,12 +13,32 @@ #define hifi_RenderableLightEntityItem_h #include +#include #include "RenderableEntityItem.h" + +class LightRenderItem { +public: + using Payload = render::Payload; + using Pointer = Payload::DataPointer; + + model::LightPointer _light; + + render::Item::Bound _bound; + + void render(RenderArgs* args); +}; + +namespace render { + template <> const ItemKey payloadGetKey(const LightRenderItem::Pointer& payload); + template <> const Item::Bound payloadGetBound(const LightRenderItem::Pointer& payload); + template <> void payloadRender(const LightRenderItem::Pointer& payload, RenderArgs* args); +} + class RenderableLightEntityItem : public LightEntityItem { public: static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties); - RenderableLightEntityItem(const EntityItemID& entityItemID) : LightEntityItem(entityItemID) { } + RenderableLightEntityItem(const EntityItemID& entityItemID); virtual void render(RenderArgs* args) override; virtual bool supportsDetailedRayIntersection() const override { return true; } @@ -27,7 +47,62 @@ public: BoxFace& face, glm::vec3& surfaceNormal, void** intersectedObject, bool precisionPicking) const override; - SIMPLE_RENDERABLE(); + void updateLightFromEntity(); + + virtual bool addToScene(EntityItemPointer self, std::shared_ptr scene, render::PendingChanges& pendingChanges) override { + _myItem = scene->allocateID(); + auto renderPayload = std::make_shared(); + + render::Item::Status::Getters statusGetters; + makeEntityItemStatusGetters(self, statusGetters); + renderPayload->addStatusGetters(statusGetters); + + pendingChanges.resetItem(_myItem, renderPayload); + + return true; + } + + virtual void removeFromScene(EntityItemPointer self, std::shared_ptr scene, render::PendingChanges& pendingChanges) override { + pendingChanges.removeItem(_myItem); + render::Item::clearID(_myItem); + } + + virtual void locationChanged(bool tellPhysics = true) override { + EntityItem::locationChanged(tellPhysics); + if (!render::Item::isValidID(_myItem)) { + return; + } + + render::PendingChanges pendingChanges; + render::ScenePointer scene = AbstractViewStateInterface::instance()->getMain3DScene(); + + pendingChanges.updateItem(_myItem, [](RenderableEntityItemProxy& data) { + }); + + scene->enqueuePendingChanges(pendingChanges); + } + + virtual void dimensionsChanged() override { + EntityItem::dimensionsChanged(); + _renderHelper.notifyChanged(); + } + + void checkFading() { + bool transparent = isTransparent(); + if (transparent != _prevIsTransparent) { + _renderHelper.notifyChanged(); + _isFading = false; + _prevIsTransparent = transparent; + } + } + +private: + SimpleRenderableEntityItem _renderHelper; + bool _prevIsTransparent { isTransparent() }; + render::ItemID _myItem { render::Item::INVALID_ITEM_ID }; + + + }; diff --git a/libraries/render-utils/src/DebugDeferredBuffer.cpp b/libraries/render-utils/src/DebugDeferredBuffer.cpp index e807ea429b..6278117b32 100644 --- a/libraries/render-utils/src/DebugDeferredBuffer.cpp +++ b/libraries/render-utils/src/DebugDeferredBuffer.cpp @@ -403,51 +403,48 @@ void DebugDeferredBuffer::run(const SceneContextPointer& sceneContext, const Ren batch.setPipeline(getPipeline(_mode, first)); - if (deferredFramebuffer) { - batch.setResourceTexture(Albedo, deferredFramebuffer->getDeferredColorTexture()); - batch.setResourceTexture(Normal, deferredFramebuffer->getDeferredNormalTexture()); - batch.setResourceTexture(Specular, deferredFramebuffer->getDeferredSpecularTexture()); - batch.setResourceTexture(Depth, deferredFramebuffer->getPrimaryDepthTexture()); - batch.setResourceTexture(Lighting, deferredFramebuffer->getLightingTexture()); - } - if (!lightStage.lights.empty()) { - batch.setResourceTexture(Shadow, lightStage.lights[0]->shadow.framebuffer->getDepthStencilBuffer()); - } + if (deferredFramebuffer) { + batch.setResourceTexture(Albedo, deferredFramebuffer->getDeferredColorTexture()); + batch.setResourceTexture(Normal, deferredFramebuffer->getDeferredNormalTexture()); + batch.setResourceTexture(Specular, deferredFramebuffer->getDeferredSpecularTexture()); + batch.setResourceTexture(Depth, deferredFramebuffer->getPrimaryDepthTexture()); + batch.setResourceTexture(Lighting, deferredFramebuffer->getLightingTexture()); + } - if (linearDepthTarget) { - batch.setResourceTexture(LinearDepth, linearDepthTarget->getLinearDepthTexture()); - batch.setResourceTexture(HalfLinearDepth, linearDepthTarget->getHalfLinearDepthTexture()); - batch.setResourceTexture(HalfNormal, linearDepthTarget->getHalfNormalTexture()); - } - if (surfaceGeometryFramebuffer) { - batch.setResourceTexture(Curvature, surfaceGeometryFramebuffer->getCurvatureTexture()); - batch.setResourceTexture(DiffusedCurvature, surfaceGeometryFramebuffer->getLowCurvatureTexture()); - } - if (ambientOcclusionFramebuffer) { - batch.setResourceTexture(AmbientOcclusion, ambientOcclusionFramebuffer->getOcclusionTexture()); - batch.setResourceTexture(AmbientOcclusionBlurred, ambientOcclusionFramebuffer->getOcclusionBlurredTexture()); - } + if (linearDepthTarget) { + batch.setResourceTexture(LinearDepth, linearDepthTarget->getLinearDepthTexture()); + batch.setResourceTexture(HalfLinearDepth, linearDepthTarget->getHalfLinearDepthTexture()); + batch.setResourceTexture(HalfNormal, linearDepthTarget->getHalfNormalTexture()); + } + if (surfaceGeometryFramebuffer) { + batch.setResourceTexture(Curvature, surfaceGeometryFramebuffer->getCurvatureTexture()); + batch.setResourceTexture(DiffusedCurvature, surfaceGeometryFramebuffer->getLowCurvatureTexture()); + } + if (ambientOcclusionFramebuffer) { + batch.setResourceTexture(AmbientOcclusion, ambientOcclusionFramebuffer->getOcclusionTexture()); + batch.setResourceTexture(AmbientOcclusionBlurred, ambientOcclusionFramebuffer->getOcclusionBlurredTexture()); + } const glm::vec4 color(1.0f, 1.0f, 1.0f, 1.0f); const glm::vec2 bottomLeft(_size.x, _size.y); const glm::vec2 topRight(_size.z, _size.w); geometryBuffer->renderQuad(batch, bottomLeft, topRight, color); - batch.setResourceTexture(Albedo, nullptr); - batch.setResourceTexture(Normal, nullptr); - batch.setResourceTexture(Specular, nullptr); - batch.setResourceTexture(Depth, nullptr); - batch.setResourceTexture(Lighting, nullptr); - batch.setResourceTexture(Shadow, nullptr); - batch.setResourceTexture(LinearDepth, nullptr); - batch.setResourceTexture(HalfLinearDepth, nullptr); - batch.setResourceTexture(HalfNormal, nullptr); + batch.setResourceTexture(Albedo, nullptr); + batch.setResourceTexture(Normal, nullptr); + batch.setResourceTexture(Specular, nullptr); + batch.setResourceTexture(Depth, nullptr); + batch.setResourceTexture(Lighting, nullptr); + batch.setResourceTexture(Shadow, nullptr); + batch.setResourceTexture(LinearDepth, nullptr); + batch.setResourceTexture(HalfLinearDepth, nullptr); + batch.setResourceTexture(HalfNormal, nullptr); - batch.setResourceTexture(Curvature, nullptr); - batch.setResourceTexture(DiffusedCurvature, nullptr); + batch.setResourceTexture(Curvature, nullptr); + batch.setResourceTexture(DiffusedCurvature, nullptr); - batch.setResourceTexture(AmbientOcclusion, nullptr); - batch.setResourceTexture(AmbientOcclusionBlurred, nullptr); + batch.setResourceTexture(AmbientOcclusion, nullptr); + batch.setResourceTexture(AmbientOcclusionBlurred, nullptr); }); } diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index 5dd4c0a232..800bf18a2c 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -99,20 +99,28 @@ void DeferredLightingEffect::init() { loadLightProgram(deferred_light_spot_vert, spot_light_frag, true, _spotLight, _spotLightLocations); // Allocate a global light representing the Global Directional light casting shadow (the sun) and the ambient light - _globalLights.push_back(0); _allocatedLights.push_back(std::make_shared()); - model::LightPointer lp = _allocatedLights[0]; lp->setType(model::Light::SUN); - - // Add the global light to the light stage (for later shadow rendering) - _lightStage.addLight(lp); - 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)); + +} + +void DeferredLightingEffect::addLight(const model::LightPointer& light) { + assert(light); + auto lightID = _lightStage.addLight(light); + if (light->getType() == model::Light::POINT) { + _pointLights.push_back(lightID); + } else { + _spotLights.push_back(lightID); + } } void DeferredLightingEffect::addPointLight(const glm::vec3& position, float radius, const glm::vec3& color, @@ -459,11 +467,14 @@ void RenderDeferredSetup::run(const render::SceneContextPointer& sceneContext, c // Global directional light and ambient pass - assert(deferredLightingEffect->getLightStage().lights.size() > 0); - const auto& globalShadow = deferredLightingEffect->getLightStage().lights[0]->shadow; + assert(deferredLightingEffect->getLightStage().getNumLights() > 0); + auto lightAndShadow = deferredLightingEffect->getLightStage().getLightAndShadow(0); + const auto& globalShadow = lightAndShadow.second; // Bind the shadow buffer - batch.setResourceTexture(SHADOW_MAP_UNIT, globalShadow.map); + if (globalShadow) { + batch.setResourceTexture(SHADOW_MAP_UNIT, globalShadow->map); + } auto& program = deferredLightingEffect->_shadowMapEnabled ? deferredLightingEffect->_directionalLightShadow : deferredLightingEffect->_directionalLight; LightLocationsPtr locations = deferredLightingEffect->_shadowMapEnabled ? deferredLightingEffect->_directionalLightShadowLocations : deferredLightingEffect->_directionalLightLocations; @@ -492,7 +503,9 @@ void RenderDeferredSetup::run(const render::SceneContextPointer& sceneContext, c } if (locations->shadowTransformBuffer >= 0) { - batch.setUniformBuffer(locations->shadowTransformBuffer, globalShadow.getBuffer()); + if (globalShadow) { + batch.setUniformBuffer(locations->shadowTransformBuffer, globalShadow->getBuffer()); + } } batch.setPipeline(program); } @@ -573,7 +586,10 @@ void RenderDeferredLocals::run(const render::SceneContextPointer& sceneContext, batch._glUniform4fv(deferredLightingEffect->_pointLightLocations->texcoordFrameTransform, 1, reinterpret_cast< const float* >(&textureFrameTransform)); for (auto lightID : deferredLightingEffect->_pointLights) { - auto& light = deferredLightingEffect->_allocatedLights[lightID]; + auto light = deferredLightingEffect->getLightStage().getLight(lightID); + if (!light) { + continue; + } // IN DEBUG: light->setShowContour(true); batch.setUniformBuffer(deferredLightingEffect->_pointLightLocations->lightBufferUnit, light->getSchemaBuffer()); @@ -613,7 +629,10 @@ void RenderDeferredLocals::run(const render::SceneContextPointer& sceneContext, auto& conePart = mesh->getPartBuffer().get(0); for (auto lightID : deferredLightingEffect->_spotLights) { - auto light = deferredLightingEffect->_allocatedLights[lightID]; + auto light = deferredLightingEffect->getLightStage().getLight(lightID); + if (!light) { + continue; + } // IN DEBUG: // light->setShowContour(true); batch.setUniformBuffer(deferredLightingEffect->_spotLightLocations->lightBufferUnit, light->getSchemaBuffer()); diff --git a/libraries/render-utils/src/DeferredLightingEffect.h b/libraries/render-utils/src/DeferredLightingEffect.h index 466c58c36e..9c8d627610 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.h +++ b/libraries/render-utils/src/DeferredLightingEffect.h @@ -43,6 +43,8 @@ class DeferredLightingEffect : public Dependency { public: void init(); + void addLight(const model::LightPointer& light); + /// Adds a point light to render for the current frame. void addPointLight(const glm::vec3& position, float radius, const glm::vec3& color = glm::vec3(0.0f, 0.0f, 0.0f), float intensity = 0.5f, float falloffRadius = 0.01f); @@ -58,6 +60,7 @@ public: void setGlobalLight(const model::LightPointer& light); const LightStage& getLightStage() { return _lightStage; } + void setShadowMapEnabled(bool enable) { _shadowMapEnabled = enable; }; void setAmbientOcclusionEnabled(bool enable) { _ambientOcclusionEnabled = enable; } bool isAmbientOcclusionEnabled() const { return _ambientOcclusionEnabled; } diff --git a/libraries/render-utils/src/LightStage.cpp b/libraries/render-utils/src/LightStage.cpp index f1726feca6..5db1f99532 100644 --- a/libraries/render-utils/src/LightStage.cpp +++ b/libraries/render-utils/src/LightStage.cpp @@ -87,10 +87,36 @@ const glm::mat4& LightStage::Shadow::getProjection() const { return _frustum->getProjection(); } -const LightStage::LightPointer LightStage::addLight(model::LightPointer light) { - // Shadow stageShadow{light}; - LightPointer stageLight = std::make_shared(Shadow(light)); - stageLight->light = light; - lights.push_back(stageLight); - return stageLight; +LightStage::Index LightStage::findLight(const LightPointer& light) const { + auto found = _lightMap.find(light); + if (found != _lightMap.end()) { + return INVALID_INDEX; + } else { + return (*found).second; + } + +} + +LightStage::Index LightStage::addLight(const LightPointer& light) { + + auto found = _lightMap.find(light); + if (found == _lightMap.end()) { + auto lightId = _lights.newElement(light); + // Avoid failing to allocate a light, just pass + if (lightId != INVALID_INDEX) { + + // Allocate the matching Desc to the light + if (lightId >= _descs.size()) { + _descs.emplace_back(Desc()); + } else { + _descs.emplace(_descs.begin() + lightId, Desc()); + } + + // INsert the light and its index in the reverese map + _lightMap.insert(LightMap::value_type(light, lightId)); + } + return lightId; + } else { + return (*found).second; + } } diff --git a/libraries/render-utils/src/LightStage.h b/libraries/render-utils/src/LightStage.h index 76d9a3b268..c6c09b9520 100644 --- a/libraries/render-utils/src/LightStage.h +++ b/libraries/render-utils/src/LightStage.h @@ -12,15 +12,161 @@ #ifndef hifi_render_utils_LightStage_h #define hifi_render_utils_LightStage_h +#include +#include + #include "gpu/Framebuffer.h" #include "model/Light.h" class ViewFrustum; +namespace indexed_elements { + + using Index = int32_t; + const Index MAXIMUM_INDEX { 1 << 30 }; + const Index INVALID_INDEX { -1 }; + using Indices = std::vector< Index >; + + template + class Allocator { + public: + Allocator() {} + Indices _freeIndices; + Index _nextNewIndex { 0 }; + + bool checkIndex(Index index) const { return ((index >= 0) && (index < _nextNewIndex)); } + Index getNumIndices() const { return _nextNewIndex - _freeIndices.size(); } + + Index allocateIndex() { + if (_freeIndices.empty()) { + Index index = _nextNewIndex; + if (index >= MaxNumElements) { + // abort! we are trying to go overboard with the total number of allocated elements + assert(false); + // This should never happen because Bricks are allocated along with the cells and there + // is already a cap on the cells allocation + return INVALID_INDEX; + } + _nextNewIndex++; + return index; + } else { + Index index = _freeIndices.back(); + _freeIndices.pop_back(); + return index; + } + } + + void freeIndex(Index index) { + if (checkIndex(index)) { + _freeIndices.push_back(index); + } + } + + void clear() { + _freeIndices.clear(); + _nextNewIndex = 0; + } + }; + + template + class IndexedVector { + Allocator _allocator; + public: + using Element = T; + using Elements = std::vector; + + Elements _elements; + + bool checkIndex(Index index) const { return _allocator.checkIndex(index); }; + Index getNumElements() const { return _allocator.getNumIndices(); } + + Index newElement(const Element& e) { + Index index = _allocator.allocateIndex(); + if (index != INVALID_INDEX) { + if (index < _elements.size()) { + _elements.emplace(_elements.begin() + index, e); + } else { + assert(index == _elements.size()); + _elements.emplace_back(e); + } + } + return index; + } + + const Element& freeElement(Index index) { + _allocator.freeIndex(index); + return _elements[index]; + } + + const Element& get(Index index) const { + return _elements[index]; + } + Element& edit(Index index) { + return _elements[index]; + } + }; + + template + class IndexedPointerVector { + Allocator _allocator; + public: + using Data = T; + using ElementPtr = std::shared_ptr; + using Elements = std::vector; + + Elements _elements; + + bool checkIndex(Index index) const { return _allocator.checkIndex(index); }; + Index getNumElements() const { return _allocator.getNumIndices(); } + + Index newElement(const ElementPtr& e) { + Index index = _allocator.allocateIndex(); + if (index != INVALID_INDEX) { + if (index < _elements.size()) { + _elements.emplace(_elements.begin() + index, e); + } else { + assert(index == _elements.size()); + _elements.emplace_back(e); + } + } + return index; + } + + ElementPtr freeElement(Index index) { + ElementPtr freed; + if (checkIndex(index)) { + _allocator.freeIndex(index); + freed = _elements[index]; + _elements[index].reset(); // really forget it + } + return freed; + } + + ElementPtr get(Index index) const { + if (checkIndex(index)) { + return _elements[index]; + } else { + return ElementPtr(); + } + } + }; + + + +}; + + // Light stage to set up light-related rendering tasks class LightStage { public: + using Index = indexed_elements::Index; + static const Index INVALID_INDEX { indexed_elements::INVALID_INDEX }; + + using LightPointer = model::LightPointer; + using Lights = indexed_elements::IndexedPointerVector; + using LightMap = std::unordered_map; + class Shadow { public: using UniformBufferView = gpu::BufferView; @@ -56,21 +202,45 @@ public: friend class Light; }; using ShadowPointer = std::shared_ptr; + using Shadows = indexed_elements::IndexedPointerVector; - class Light { - public: - Light(Shadow&& shadow) : shadow{ shadow } {} - - model::LightPointer light; - Shadow shadow; + struct Desc { + Index shadowId { INVALID_INDEX }; }; - using LightPointer = std::shared_ptr; - using Lights = std::vector; + using Descs = std::vector; - const LightPointer addLight(model::LightPointer light); - // TODO: removeLight - Lights lights; + Index findLight(const LightPointer& light) const; + Index addLight(const LightPointer& light); + + bool checkLightId(Index index) const { return _lights.checkIndex(index); } + + Index getNumLights() const { return _lights.getNumElements(); } + + LightPointer getLight(Index lightId) const { + return _lights.get(lightId); + } + Index getShadowId(Index lightId) const { + if (checkLightId(lightId)) { + return _descs[lightId].shadowId; + } else { + return INVALID_INDEX; + } + } + ShadowPointer getShadow(Index lightId) const { + return _shadows.get(getShadowId(lightId)); + } + + using LightAndShadow = std::pair; + LightAndShadow getLightAndShadow(Index lightId) const { + return LightAndShadow(getLight(lightId), getShadow(lightId)); + } + + Lights _lights; + LightMap _lightMap; + Descs _descs; + + Shadows _shadows; }; #endif diff --git a/libraries/render-utils/src/RenderShadowTask.cpp b/libraries/render-utils/src/RenderShadowTask.cpp index 237c01cf28..2efbe7bf89 100644 --- a/libraries/render-utils/src/RenderShadowTask.cpp +++ b/libraries/render-utils/src/RenderShadowTask.cpp @@ -37,9 +37,14 @@ void RenderShadowMap::run(const render::SceneContextPointer& sceneContext, const assert(renderContext->args->hasViewFrustum()); const auto& lightStage = DependencyManager::get()->getLightStage(); - const auto globalLight = lightStage.lights[0]; - const auto& shadow = globalLight->shadow; - const auto& fbo = shadow.framebuffer; + + LightStage::Index globalLightIndex { 0 }; + + const auto globalLight = lightStage.getLight(globalLightIndex); + const auto shadow = lightStage.getShadow(globalLightIndex); + if (!shadow) return; + + const auto& fbo = shadow->framebuffer; RenderArgs* args = renderContext->args; gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { @@ -54,8 +59,8 @@ void RenderShadowMap::run(const render::SceneContextPointer& sceneContext, const gpu::Framebuffer::BUFFER_COLOR0 | gpu::Framebuffer::BUFFER_DEPTH, vec4(vec3(1.0, 1.0, 1.0), 0.0), 1.0, 0, true); - batch.setProjectionTransform(shadow.getProjection()); - batch.setViewTransform(shadow.getView(), false); + batch.setProjectionTransform(shadow->getProjection()); + batch.setViewTransform(shadow->getView(), false); auto shadowPipeline = _shapePlumber->pickPipeline(args, ShapeKey()); auto shadowSkinnedPipeline = _shapePlumber->pickPipeline(args, ShapeKey::Builder().withSkinned()); @@ -140,10 +145,10 @@ void RenderShadowTask::run(const SceneContextPointer& sceneContext, const render } const auto& lightStage = DependencyManager::get()->getLightStage(); - const auto globalLight = lightStage.lights[0]; + const auto globalShadow = lightStage.getShadow(0); // If the global light is not set, bail - if (!globalLight) { + if (!globalShadow) { return; } @@ -153,10 +158,10 @@ void RenderShadowTask::run(const SceneContextPointer& sceneContext, const render auto nearClip = args->getViewFrustum().getNearClip(); float nearDepth = -args->_boomOffset.z; const int SHADOW_FAR_DEPTH = 20; - globalLight->shadow.setKeylightFrustum(args->getViewFrustum(), nearDepth, nearClip + SHADOW_FAR_DEPTH); + globalShadow->setKeylightFrustum(args->getViewFrustum(), nearDepth, nearClip + SHADOW_FAR_DEPTH); // Set the keylight render args - args->pushViewFrustum(*(globalLight->shadow.getFrustum())); + args->pushViewFrustum(*(globalShadow->getFrustum())); args->_renderMode = RenderArgs::SHADOW_RENDER_MODE; // TODO: Allow runtime manipulation of culling ShouldRenderFunctor diff --git a/libraries/render-utils/src/SubsurfaceScattering.cpp b/libraries/render-utils/src/SubsurfaceScattering.cpp index f1aec66433..d78cbdb304 100644 --- a/libraries/render-utils/src/SubsurfaceScattering.cpp +++ b/libraries/render-utils/src/SubsurfaceScattering.cpp @@ -530,7 +530,7 @@ void DebugSubsurfaceScattering::run(const render::SceneContextPointer& sceneCont - const auto theLight = DependencyManager::get()->getLightStage().lights[0]; + const auto light = DependencyManager::get()->getLightStage().getLight(0); gpu::doInBatch(args->_context, [=](gpu::Batch& batch) { batch.enableStereo(false); @@ -564,8 +564,8 @@ void DebugSubsurfaceScattering::run(const render::SceneContextPointer& sceneCont batch.setUniformBuffer(ScatteringTask_FrameTransformSlot, frameTransform->getFrameTransformBuffer()); batch.setUniformBuffer(ScatteringTask_ParamSlot, scatteringResource->getParametersBuffer()); - if (theLight->light) { - batch.setUniformBuffer(ScatteringTask_LightSlot, theLight->light->getSchemaBuffer()); + if (light) { + batch.setUniformBuffer(ScatteringTask_LightSlot, light->getSchemaBuffer()); } batch.setResourceTexture(ScatteringTask_ScatteringTableSlot, scatteringTable); batch.setResourceTexture(ScatteringTask_CurvatureMapSlot, curvatureFramebuffer->getRenderBuffer(0));