From 4bf93f66df02f64aed7bdc9c49841a41af1ac7a7 Mon Sep 17 00:00:00 2001 From: samcake Date: Fri, 26 Aug 2016 17:47:20 -0700 Subject: [PATCH 01/75] Cleaning up the lights and the light stage --- .../src/RenderableLightEntityItem.cpp | 73 +++++-- .../src/RenderableLightEntityItem.h | 79 ++++++- .../render-utils/src/DebugDeferredBuffer.cpp | 69 +++---- .../src/DeferredLightingEffect.cpp | 43 ++-- .../render-utils/src/DeferredLightingEffect.h | 3 + libraries/render-utils/src/LightStage.cpp | 38 +++- libraries/render-utils/src/LightStage.h | 192 +++++++++++++++++- .../render-utils/src/RenderShadowTask.cpp | 23 ++- .../render-utils/src/SubsurfaceScattering.cpp | 6 +- 9 files changed, 430 insertions(+), 96 deletions(-) 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)); From 3755a3fc32282942f244fc5ba329bf9e0a600fc4 Mon Sep 17 00:00:00 2001 From: samcake Date: Mon, 29 Aug 2016 17:54:17 -0700 Subject: [PATCH 02/75] Add batch timing information vs gpu --- .../src/RenderableLightEntityItem.cpp | 135 +++++++++++------- .../src/RenderableLightEntityItem.h | 52 ++++--- libraries/entities/src/EntityItem.h | 3 + .../gpu-gl/src/gpu/gl/GLBackendQuery.cpp | 7 +- libraries/gpu-gl/src/gpu/gl/GLQuery.h | 1 + libraries/gpu/src/gpu/Query.cpp | 21 ++- libraries/gpu/src/gpu/Query.h | 11 +- .../src/AmbientOcclusionEffect.cpp | 4 +- .../render-utils/src/AmbientOcclusionEffect.h | 5 +- .../src/DeferredLightingEffect.cpp | 3 +- .../render-utils/src/DeferredLightingEffect.h | 5 +- .../render-utils/src/RenderDeferredTask.cpp | 2 +- .../render-utils/src/RenderDeferredTask.h | 20 ++- .../render-utils/src/SurfaceGeometryPass.cpp | 8 +- .../render-utils/src/SurfaceGeometryPass.h | 10 +- .../developer/utilities/render/statsGPU.qml | 41 ++++++ 16 files changed, 230 insertions(+), 98 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableLightEntityItem.cpp b/libraries/entities-renderer/src/RenderableLightEntityItem.cpp index 3264ecb077..4a62a5b652 100644 --- a/libraries/entities-renderer/src/RenderableLightEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableLightEntityItem.cpp @@ -25,69 +25,29 @@ EntityItemPointer RenderableLightEntityItem::factory(const EntityItemID& entityI return entity; } -RenderableLightEntityItem::RenderableLightEntityItem(const EntityItemID& entityItemID) : LightEntityItem(entityItemID), - _light(std::make_shared()), - _lightStamp(-1) +RenderableLightEntityItem::RenderableLightEntityItem(const EntityItemID& entityItemID) : LightEntityItem(entityItemID) { } -namespace render { - template <> const ItemKey payloadGetKey(const LightPayload::Pointer& payload) { - return ItemKey::Builder::light(); +void RenderableLightEntityItem::updateLightFromEntity(render::PendingChanges& pendingChanges) { + if (!render::Item::isValidID(_myItem)) { + return; } - 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); - } - } - } + + pendingChanges.updateItem(_myItem, [this](LightRenderItem& data) { + data.updateLightFromEntity(this); + }); } - -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(); - updateLightFromEntity(); - DependencyManager::get()->addLight(_light); + // DependencyManager::get()->addLight(_light); #ifdef WANT_DEBUG Q_ASSERT(args->_batch); @@ -96,6 +56,7 @@ void RenderableLightEntityItem::render(RenderArgs* args) { DependencyManager::get()->renderWireSphere(batch, 0.5f, 15, 15, glm::vec4(color, 1.0f)); #endif }; +*/ bool RenderableLightEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, bool& keepSearching, OctreeElementPointer& element, float& distance, @@ -109,3 +70,77 @@ bool RenderableLightEntityItem::findDetailedRayIntersection(const glm::vec3& ori // fix this mechanism. return _lightsArePickable; } + + + +namespace render { + template <> const ItemKey payloadGetKey(const LightRenderItem::Pointer& payload) { + return ItemKey::Builder::light(); + } + + template <> const Item::Bound payloadGetBound(const LightRenderItem::Pointer& payload) { + if (payload) { + return payload->_bound; + } + return render::Item::Bound(); + } + template <> void payloadRender(const LightRenderItem::Pointer& payload, RenderArgs* args) { + if (args) { + if (payload) { + payload->render(args); + } + } + } +} + +LightRenderItem::LightRenderItem() : +_light(std::make_shared()) +{ +} + +void LightRenderItem::updateLightFromEntity(RenderableLightEntityItem* entity) { + _light->setPosition(entity->getPosition()); + _light->setOrientation(entity->getRotation()); + + bool success; + _bound = entity->getAABox(success); + if (!success) { + _bound = render::Item::Bound(); + } + + glm::vec3 dimensions = entity->getDimensions(); + float largestDiameter = glm::max(dimensions.x, dimensions.y, dimensions.z); + _light->setMaximumRadius(largestDiameter / 2.0f); + + _light->setColor(toGlm(entity->getXColor())); + + float intensity = entity->getIntensity();//* entity->getFadingRatio(); + _light->setIntensity(intensity); + + _light->setFalloffRadius(entity->getFalloffRadius()); + + + float exponent = entity->getExponent(); + float cutoff = glm::radians(entity->getCutoff()); + if (!entity->getIsSpotlight()) { + _light->setType(model::Light::POINT); + } else { + _light->setType(model::Light::SPOT); + + _light->setSpotAngle(cutoff); + _light->setSpotExponent(exponent); + } + +} + + +void LightRenderItem::render(RenderArgs* args) { + + //updateLightFromEntity(); + + DependencyManager::get()->addLight(_light); + +} + + + diff --git a/libraries/entities-renderer/src/RenderableLightEntityItem.h b/libraries/entities-renderer/src/RenderableLightEntityItem.h index c6e6aa7216..1b6deae6ad 100644 --- a/libraries/entities-renderer/src/RenderableLightEntityItem.h +++ b/libraries/entities-renderer/src/RenderableLightEntityItem.h @@ -16,6 +16,7 @@ #include #include "RenderableEntityItem.h" +class RenderableLightEntityItem; class LightRenderItem { public: @@ -26,7 +27,11 @@ public: render::Item::Bound _bound; + LightRenderItem(); void render(RenderArgs* args); + + void updateLightFromEntity(RenderableLightEntityItem* entity); + }; namespace render { @@ -40,18 +45,22 @@ public: static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties); RenderableLightEntityItem(const EntityItemID& entityItemID); - virtual void render(RenderArgs* args) override; + virtual bool supportsDetailedRayIntersection() const override { return true; } virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, bool& keepSearching, OctreeElementPointer& element, float& distance, BoxFace& face, glm::vec3& surfaceNormal, void** intersectedObject, bool precisionPicking) const override; - void updateLightFromEntity(); + void updateLightFromEntity(render::PendingChanges& pendingChanges); virtual bool addToScene(EntityItemPointer self, std::shared_ptr scene, render::PendingChanges& pendingChanges) override { _myItem = scene->allocateID(); - auto renderPayload = std::make_shared(); + + auto renderItem = std::make_shared(); + renderItem->updateLightFromEntity(this); + + auto renderPayload = std::make_shared(renderItem); render::Item::Status::Getters statusGetters; makeEntityItemStatusGetters(self, statusGetters); @@ -69,6 +78,25 @@ public: virtual void locationChanged(bool tellPhysics = true) override { EntityItem::locationChanged(tellPhysics); + notifyChanged(); + } + + virtual void dimensionsChanged() override { + EntityItem::dimensionsChanged(); + notifyChanged(); + } + + void checkFading() { + bool transparent = isTransparent(); + if (transparent != _prevIsTransparent) { + notifyChanged(); + _isFading = false; + _prevIsTransparent = transparent; + } + } + + void notifyChanged() { + if (!render::Item::isValidID(_myItem)) { return; } @@ -76,28 +104,12 @@ public: render::PendingChanges pendingChanges; render::ScenePointer scene = AbstractViewStateInterface::instance()->getMain3DScene(); - pendingChanges.updateItem(_myItem, [](RenderableEntityItemProxy& data) { - }); + updateLightFromEntity(pendingChanges); 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/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index e572bf4de8..bbc0a1728c 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -446,6 +446,9 @@ public: virtual void setProxyWindow(QWindow* proxyWindow) {} virtual QObject* getEventHandler() { return nullptr; } + bool isFading() const { return _isFading; } + float getFadingRatio() const { return (isFading() ? Interpolate::calculateFadeRatio(_fadeStartTime) : 1.0f); } + protected: void setSimulated(bool simulated) { _simulated = simulated; } diff --git a/libraries/gpu-gl/src/gpu/gl/GLBackendQuery.cpp b/libraries/gpu-gl/src/gpu/gl/GLBackendQuery.cpp index 60b204ba60..b693991f1c 100644 --- a/libraries/gpu-gl/src/gpu/gl/GLBackendQuery.cpp +++ b/libraries/gpu-gl/src/gpu/gl/GLBackendQuery.cpp @@ -25,6 +25,7 @@ void GLBackend::do_beginQuery(const Batch& batch, size_t paramOffset) { auto query = batch._queries.get(batch._params[paramOffset]._uint); GLQuery* glquery = syncGPUObject(*query); if (glquery) { + glGetInteger64v(GL_TIMESTAMP, (GLint64*) &glquery->_batchTimeRange); if (timeElapsed) { glBeginQuery(GL_TIME_ELAPSED, glquery->_endqo); } else { @@ -43,6 +44,10 @@ void GLBackend::do_endQuery(const Batch& batch, size_t paramOffset) { } else { glQueryCounter(glquery->_endqo, GL_TIMESTAMP); } + GLint64 now; + glGetInteger64v(GL_TIMESTAMP, &now); + glquery->_batchTimeRange = now - glquery->_batchTimeRange; + (void)CHECK_GL_ERROR(); } } @@ -61,7 +66,7 @@ void GLBackend::do_getQuery(const Batch& batch, size_t paramOffset) { glGetQueryObjectui64v(glquery->_endqo, GL_QUERY_RESULT, &end); glquery->_result = end - start; } - query->triggerReturnHandler(glquery->_result); + query->triggerReturnHandler(glquery->_result, ((double) glquery->_batchTimeRange) / 1000000.0); } (void)CHECK_GL_ERROR(); } diff --git a/libraries/gpu-gl/src/gpu/gl/GLQuery.h b/libraries/gpu-gl/src/gpu/gl/GLQuery.h index 4bed659ba3..61efd20e78 100644 --- a/libraries/gpu-gl/src/gpu/gl/GLQuery.h +++ b/libraries/gpu-gl/src/gpu/gl/GLQuery.h @@ -48,6 +48,7 @@ public: const GLuint& _endqo = { _id }; const GLuint _beginqo = { 0 }; GLuint64 _result { (GLuint64)-1 }; + GLuint64 _batchTimeRange; protected: GLQuery(const std::weak_ptr& backend, const Query& query, GLuint endId, GLuint beginId) : Parent(backend, query, endId), _beginqo(beginId) {} diff --git a/libraries/gpu/src/gpu/Query.cpp b/libraries/gpu/src/gpu/Query.cpp index 76c239b1e0..e5653a74f4 100644 --- a/libraries/gpu/src/gpu/Query.cpp +++ b/libraries/gpu/src/gpu/Query.cpp @@ -28,8 +28,14 @@ double Query::getElapsedTime() const { return ((double)_queryResult) / 1000000.0; } -void Query::triggerReturnHandler(uint64_t queryResult) { +double Query::getBatchPerformTime() const { + return _batchPerformTime; +} + +void Query::triggerReturnHandler(uint64_t queryResult, double cpuTime) { _queryResult = queryResult; + _batchPerformTime = cpuTime; + if (_returnHandler) { _returnHandler(*this); } @@ -41,7 +47,10 @@ RangeTimer::RangeTimer() { _timerQueries.push_back(std::make_shared([&, i] (const Query& query) { _tailIndex ++; auto elapsedTime = query.getElapsedTime(); - _movingAverage.addSample(elapsedTime); + _movingAverageGPU.addSample(elapsedTime); + + auto elapsedTimeCPU = query.getBatchPerformTime(); + _movingAverageCPU.addSample(elapsedTimeCPU); })); } } @@ -66,6 +75,10 @@ void RangeTimer::end(gpu::Batch& batch) { } } -double RangeTimer::getAverage() const { - return _movingAverage.average; +double RangeTimer::getAverageGPU() const { + return _movingAverageGPU.average; +} + +double RangeTimer::getAverageCPU() const { + return _movingAverageCPU.average; } \ No newline at end of file diff --git a/libraries/gpu/src/gpu/Query.h b/libraries/gpu/src/gpu/Query.h index 48b9d0a0d5..9bcedb9d17 100644 --- a/libraries/gpu/src/gpu/Query.h +++ b/libraries/gpu/src/gpu/Query.h @@ -32,12 +32,15 @@ namespace gpu { double getElapsedTime() const; + double getBatchPerformTime() const; + const GPUObjectPointer gpuObject {}; - void triggerReturnHandler(uint64_t queryResult); + void triggerReturnHandler(uint64_t queryResult, double cpuTime); protected: Handler _returnHandler; uint64_t _queryResult = 0; + double _batchPerformTime { 0.0 }; }; typedef std::shared_ptr QueryPointer; @@ -53,7 +56,8 @@ namespace gpu { void begin(gpu::Batch& batch); void end(gpu::Batch& batch); - double getAverage() const; + double getAverageGPU() const; + double getAverageCPU() const; protected: @@ -62,7 +66,8 @@ namespace gpu { gpu::Queries _timerQueries; int _headIndex = -1; int _tailIndex = -1; - MovingAverage _movingAverage; + MovingAverage _movingAverageCPU; + MovingAverage _movingAverageGPU; int rangeIndex(int index) const { return (index % QUERY_QUEUE_SIZE); } }; diff --git a/libraries/render-utils/src/AmbientOcclusionEffect.cpp b/libraries/render-utils/src/AmbientOcclusionEffect.cpp index 86223e9877..d419f619cb 100644 --- a/libraries/render-utils/src/AmbientOcclusionEffect.cpp +++ b/libraries/render-utils/src/AmbientOcclusionEffect.cpp @@ -432,7 +432,9 @@ void AmbientOcclusionEffect::run(const render::SceneContextPointer& sceneContext }); // Update the timer - std::static_pointer_cast(renderContext->jobConfig)->gpuTime = _gpuTimer.getAverage(); + auto config = std::static_pointer_cast(renderContext->jobConfig); + config->gpuTime = _gpuTimer.getAverageGPU(); + config->gpuBatchTime = _gpuTimer.getAverageCPU(); } diff --git a/libraries/render-utils/src/AmbientOcclusionEffect.h b/libraries/render-utils/src/AmbientOcclusionEffect.h index 8bb4600d3c..e10d5fd0c7 100644 --- a/libraries/render-utils/src/AmbientOcclusionEffect.h +++ b/libraries/render-utils/src/AmbientOcclusionEffect.h @@ -69,6 +69,7 @@ class AmbientOcclusionEffectConfig : public render::Job::Config::Persistent { Q_PROPERTY(int resolutionLevel MEMBER resolutionLevel WRITE setResolutionLevel) Q_PROPERTY(int blurRadius MEMBER blurRadius WRITE setBlurRadius) Q_PROPERTY(double gpuTime READ getGpuTime) + Q_PROPERTY(double gpuBatchTime READ getGpuBatchTime) public: AmbientOcclusionEffectConfig() : render::Job::Config::Persistent("Ambient Occlusion", false) {} @@ -85,6 +86,7 @@ public: void setResolutionLevel(int level) { resolutionLevel = std::max(0, std::min(level, MAX_RESOLUTION_LEVEL)); emit dirty(); } void setBlurRadius(int radius) { blurRadius = std::max(0, std::min(MAX_BLUR_RADIUS, radius)); emit dirty(); } double getGpuTime() { return gpuTime; } + double getGpuBatchTime() { return gpuBatchTime; } float radius{ 0.5f }; float perspectiveScale{ 1.0f }; @@ -99,7 +101,8 @@ public: bool ditheringEnabled{ true }; // randomize the distribution of taps per pixel, should always be true bool borderingEnabled{ true }; // avoid evaluating information from non existing pixels out of the frame, should always be true bool fetchMipsEnabled{ true }; // fetch taps in sub mips to otpimize cache, should always be true - double gpuTime{ 0.0 }; + double gpuTime { 0.0 }; + double gpuBatchTime { 0.0 }; signals: void dirty(); diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index 800bf18a2c..331762f9ac 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -733,5 +733,6 @@ void RenderDeferred::run(const SceneContextPointer& sceneContext, const RenderCo }); auto config = std::static_pointer_cast(renderContext->jobConfig); - config->gpuTime = _gpuTimer.getAverage(); + config->gpuTime = _gpuTimer.getAverageGPU(); + config->gpuBatchTime = _gpuTimer.getAverageCPU(); } diff --git a/libraries/render-utils/src/DeferredLightingEffect.h b/libraries/render-utils/src/DeferredLightingEffect.h index 9c8d627610..83c8a8e6b9 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.h +++ b/libraries/render-utils/src/DeferredLightingEffect.h @@ -168,12 +168,15 @@ public: class RenderDeferredConfig : public render::Job::Config { Q_OBJECT Q_PROPERTY(double gpuTime READ getGpuTime) + Q_PROPERTY(double gpuBatchTime READ getGpuBatchTime) public: RenderDeferredConfig() : render::Job::Config(true) {} double getGpuTime() { return gpuTime; } + double getGpuBatchTime() { return gpuBatchTime; } - double gpuTime{ 0.0 }; + double gpuTime { 0.0 }; + double gpuBatchTime { 0.0 }; signals: void dirty(); diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index cedc2ef45e..2ff122ab1a 100755 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -245,7 +245,7 @@ void EndGPURangeTimer::run(const render::SceneContextPointer& sceneContext, cons }); auto config = std::static_pointer_cast(renderContext->jobConfig); - config->gpuTime = timer->getAverage(); + config->setTime(timer->getAverageGPU(), timer->getAverageCPU()); } diff --git a/libraries/render-utils/src/RenderDeferredTask.h b/libraries/render-utils/src/RenderDeferredTask.h index 749cc09edc..5b321abc54 100755 --- a/libraries/render-utils/src/RenderDeferredTask.h +++ b/libraries/render-utils/src/RenderDeferredTask.h @@ -33,12 +33,19 @@ protected: class GPURangeTimerConfig : public render::Job::Config { Q_OBJECT Q_PROPERTY(double gpuTime READ getGpuTime) + Q_PROPERTY(double gpuBatchTime READ getGpuBatchTime) public: double getGpuTime() { return gpuTime; } + double getGpuBatchTime() { return gpuBatchTime; } + void setTime(double gpu, double batch) { + gpuTime = gpu; + gpuBatchTime = batch; + } + protected: - friend class EndGPURangeTimer; double gpuTime; + double gpuBatchTime; }; class EndGPURangeTimer { @@ -143,16 +150,7 @@ protected: gpu::PipelinePointer getOpaquePipeline(); }; -class DrawBackgroundDeferredConfig : public render::Job::Config { - Q_OBJECT - Q_PROPERTY(double gpuTime READ getGpuTime) -public: - double getGpuTime() { return gpuTime; } - -protected: - friend class DrawBackgroundDeferred; - double gpuTime; -}; +using DrawBackgroundDeferredConfig = GPURangeTimerConfig; class DrawBackgroundDeferred { public: diff --git a/libraries/render-utils/src/SurfaceGeometryPass.cpp b/libraries/render-utils/src/SurfaceGeometryPass.cpp index 7a5a34c756..9f37f72e3a 100644 --- a/libraries/render-utils/src/SurfaceGeometryPass.cpp +++ b/libraries/render-utils/src/SurfaceGeometryPass.cpp @@ -201,7 +201,9 @@ void LinearDepthPass::run(const render::SceneContextPointer& sceneContext, const }); auto config = std::static_pointer_cast(renderContext->jobConfig); - config->gpuTime = _gpuTimer.getAverage(); + config->gpuTime = _gpuTimer.getAverageGPU(); + config->gpuBatchTime = _gpuTimer.getAverageCPU(); + } @@ -524,8 +526,8 @@ void SurfaceGeometryPass::run(const render::SceneContextPointer& sceneContext, c auto config = std::static_pointer_cast(renderContext->jobConfig); - config->gpuTime = _gpuTimer.getAverage(); -} + config->gpuTime = _gpuTimer.getAverageGPU(); + config->gpuBatchTime = _gpuTimer.getAverageCPU(); } const gpu::PipelinePointer& SurfaceGeometryPass::getCurvaturePipeline() { diff --git a/libraries/render-utils/src/SurfaceGeometryPass.h b/libraries/render-utils/src/SurfaceGeometryPass.h index 24f0c56cdd..09d9876fc6 100644 --- a/libraries/render-utils/src/SurfaceGeometryPass.h +++ b/libraries/render-utils/src/SurfaceGeometryPass.h @@ -66,12 +66,16 @@ using LinearDepthFramebufferPointer = std::shared_ptr; class LinearDepthPassConfig : public render::Job::Config { Q_OBJECT Q_PROPERTY(double gpuTime READ getGpuTime) + Q_PROPERTY(double gpuBatchTime READ getGpuBatchTime) + public: LinearDepthPassConfig() : render::Job::Config(true) {} double getGpuTime() { return gpuTime; } + double getGpuBatchTime() { return gpuBatchTime; } double gpuTime{ 0.0 }; + double gpuBatchTime { 0.0 }; signals: void dirty(); @@ -159,6 +163,8 @@ class SurfaceGeometryPassConfig : public render::Job::Config { Q_PROPERTY(float diffuseDepthThreshold MEMBER diffuseDepthThreshold NOTIFY dirty) Q_PROPERTY(double gpuTime READ getGpuTime) + Q_PROPERTY(double gpuBatchTime READ getGpuBatchTime) + public: SurfaceGeometryPassConfig() : render::Job::Config(true) {} @@ -170,8 +176,10 @@ public: float diffuseDepthThreshold{ 1.0f }; double getGpuTime() { return gpuTime; } + double getGpuBatchTime() { return gpuBatchTime; } - double gpuTime{ 0.0 }; + double gpuTime { 0.0 }; + double gpuBatchTime { 0.0 }; signals: void dirty(); diff --git a/scripts/developer/utilities/render/statsGPU.qml b/scripts/developer/utilities/render/statsGPU.qml index 74bd376a00..81e70892d4 100644 --- a/scripts/developer/utilities/render/statsGPU.qml +++ b/scripts/developer/utilities/render/statsGPU.qml @@ -69,6 +69,47 @@ Item { } ] } + + PlotPerf { + title: "Batch Timing" + height: parent.evalEvenHeight() + object: parent.drawOpaqueConfig + valueUnit: "ms" + valueScale: 1 + valueNumDigits: "4" + plots: [ + { + object: Render.getConfig("OpaqueRangeTimer"), + prop: "gpuBatchTime", + label: "Opaque", + color: "#FFFFFF" + }, + { + object: Render.getConfig("LinearDepth"), + prop: "gpuBatchTime", + label: "LinearDepth", + color: "#00FF00" + },{ + object: Render.getConfig("SurfaceGeometry"), + prop: "gpuBatchTime", + label: "SurfaceGeometry", + color: "#00FFFF" + }, + { + object: Render.getConfig("RenderDeferred"), + prop: "gpuBatchTime", + label: "DeferredLighting", + color: "#FF00FF" + } + , + { + object: Render.getConfig("ToneAndPostRangeTimer"), + prop: "gpuBatchTime", + label: "tone and post", + color: "#FF0000" + } + ] + } } } From 93aec28c7b2912d52f025134a7f0904c0ba96a3d Mon Sep 17 00:00:00 2001 From: samcake Date: Tue, 30 Aug 2016 14:54:58 -0700 Subject: [PATCH 03/75] Less warning --- libraries/render-utils/src/DeferredLightingEffect.cpp | 2 ++ libraries/render-utils/src/LightStage.h | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index 331762f9ac..b21bee91da 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -710,6 +710,8 @@ void RenderDeferred::configure(const Config& config) { } void RenderDeferred::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const Inputs& inputs) { + PROFILE_RANGE("DeferredLighting"); + auto deferredTransform = inputs.get0(); auto deferredFramebuffer = inputs.get1(); auto lightingModel = inputs.get2(); diff --git a/libraries/render-utils/src/LightStage.h b/libraries/render-utils/src/LightStage.h index c6c09b9520..a050bb393f 100644 --- a/libraries/render-utils/src/LightStage.h +++ b/libraries/render-utils/src/LightStage.h @@ -36,7 +36,7 @@ namespace indexed_elements { Index _nextNewIndex { 0 }; bool checkIndex(Index index) const { return ((index >= 0) && (index < _nextNewIndex)); } - Index getNumIndices() const { return _nextNewIndex - _freeIndices.size(); } + Index getNumIndices() const { return _nextNewIndex - (Index) _freeIndices.size(); } Index allocateIndex() { if (_freeIndices.empty()) { From b563e280e4d683a48ee2ddaf1024dea509c18136 Mon Sep 17 00:00:00 2001 From: samcake Date: Wed, 31 Aug 2016 13:55:41 -0700 Subject: [PATCH 04/75] Commuting the LIghtEntityItem changes correctly to the LightRenderItem --- .../src/RenderableLightEntityItem.h | 10 ++++-- libraries/entities/src/EntityItem.cpp | 4 +++ libraries/entities/src/EntityItem.h | 7 ++++ libraries/entities/src/LightEntityItem.cpp | 34 +++++++++++++------ libraries/entities/src/LightEntityItem.h | 26 ++++++++++++-- libraries/shared/src/shared/NsightHelpers.cpp | 9 +++-- 6 files changed, 72 insertions(+), 18 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableLightEntityItem.h b/libraries/entities-renderer/src/RenderableLightEntityItem.h index 1b6deae6ad..883af056aa 100644 --- a/libraries/entities-renderer/src/RenderableLightEntityItem.h +++ b/libraries/entities-renderer/src/RenderableLightEntityItem.h @@ -45,7 +45,6 @@ public: static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties); RenderableLightEntityItem(const EntityItemID& entityItemID); - virtual bool supportsDetailedRayIntersection() const override { return true; } virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, bool& keepSearching, OctreeElementPointer& element, float& distance, @@ -71,6 +70,13 @@ public: return true; } + virtual void somethingChangedNotification() override { + if (_lightPropertiesChanged) { + notifyChanged(); + } + LightEntityItem::somethingChangedNotification(); + } + virtual void removeFromScene(EntityItemPointer self, std::shared_ptr scene, render::PendingChanges& pendingChanges) override { pendingChanges.removeItem(_myItem); render::Item::clearID(_myItem); @@ -113,7 +119,7 @@ private: bool _prevIsTransparent { isTransparent() }; render::ItemID _myItem { render::Item::INVALID_ITEM_ID }; - + // Dirty flag turn true when either setSubClassProperties or readEntitySubclassDataFromBuffer is changing a value }; diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 68636415f8..849019fc4b 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -1313,6 +1313,10 @@ bool EntityItem::setProperties(const EntityItemProperties& properties) { somethingChanged = true; } + // Now check the sub classes + somethingChanged |= setSubClassProperties(properties); + + // Finally notify if change detected if (somethingChanged) { uint64_t now = usecTimestampNow(); #ifdef WANT_DEBUG diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index bbc0a1728c..85080ccc0a 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -90,7 +90,14 @@ public: virtual EntityItemProperties getProperties(EntityPropertyFlags desiredProperties = EntityPropertyFlags()) const; /// returns true if something changed + // THis function calls setSubClass properties and detects if any property changes value. + // If something changed then the "somethingChangedNotification" calls happens virtual bool setProperties(const EntityItemProperties& properties); + + // Set properties for sub class so they can add their own properties + // it does nothing in the root eclass + virtual bool setSubClassProperties(const EntityItemProperties& properties) { return false; } + // Update properties with empty parent id and globalized/absolute values (applying offset), and apply (non-empty) log template to args id, name-or-type, parent id. void globalizeProperties(EntityItemProperties& properties, const QString& messageTemplate = QString(), const glm::vec3& offset = glm::vec3(0.0f)) const; diff --git a/libraries/entities/src/LightEntityItem.cpp b/libraries/entities/src/LightEntityItem.cpp index 1be133463c..ad05b33e3d 100644 --- a/libraries/entities/src/LightEntityItem.cpp +++ b/libraries/entities/src/LightEntityItem.cpp @@ -70,6 +70,7 @@ EntityItemProperties LightEntityItem::getProperties(EntityPropertyFlags desiredP void LightEntityItem::setFalloffRadius(float value) { _falloffRadius = glm::max(value, 0.0f); + _lightPropertiesChanged = true; } void LightEntityItem::setIsSpotlight(bool value) { @@ -85,6 +86,7 @@ void LightEntityItem::setIsSpotlight(bool value) { float maxDimension = glm::max(dimensions.x, dimensions.y, dimensions.z); setDimensions(glm::vec3(maxDimension, maxDimension, maxDimension)); } + _lightPropertiesChanged = true; } } @@ -98,10 +100,26 @@ void LightEntityItem::setCutoff(float value) { const float width = length * glm::sin(glm::radians(_cutoff)); setDimensions(glm::vec3(width, width, length)); } + _lightPropertiesChanged = true; } bool LightEntityItem::setProperties(const EntityItemProperties& properties) { bool somethingChanged = EntityItem::setProperties(properties); // set the properties in our base class + if (somethingChanged) { + bool wantDebug = false; + if (wantDebug) { + uint64_t now = usecTimestampNow(); + int elapsed = now - getLastEdited(); + qCDebug(entities) << "LightEntityItem::setProperties() AFTER update... edited AGO=" << elapsed << + "now=" << now << " getLastEdited()=" << getLastEdited(); + } + setLastEdited(properties.getLastEdited()); + } + return somethingChanged; +} + +bool LightEntityItem::setSubClassProperties(const EntityItemProperties& properties) { + bool somethingChanged = EntityItem::setSubClassProperties(properties); // set the properties in our base class SET_ENTITY_PROPERTY_FROM_PROPERTIES(isSpotlight, setIsSpotlight); SET_ENTITY_PROPERTY_FROM_PROPERTIES(color, setColor); @@ -110,19 +128,10 @@ bool LightEntityItem::setProperties(const EntityItemProperties& properties) { SET_ENTITY_PROPERTY_FROM_PROPERTIES(cutoff, setCutoff); SET_ENTITY_PROPERTY_FROM_PROPERTIES(falloffRadius, setFalloffRadius); - if (somethingChanged) { - bool wantDebug = false; - if (wantDebug) { - uint64_t now = usecTimestampNow(); - int elapsed = now - getLastEdited(); - qCDebug(entities) << "LightEntityItem::setProperties() AFTER update... edited AGO=" << elapsed << - "now=" << now << " getLastEdited()=" << getLastEdited(); - } - setLastEdited(properties.getLastEdited()); - } return somethingChanged; } + int LightEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead, ReadBitstreamToTreeParams& args, EntityPropertyFlags& propertyFlags, bool overwriteLocalData, @@ -193,3 +202,8 @@ void LightEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBit APPEND_ENTITY_PROPERTY(PROP_CUTOFF, getCutoff()); APPEND_ENTITY_PROPERTY(PROP_FALLOFF_RADIUS, getFalloffRadius()); } + +void LightEntityItem::somethingChangedNotification() { + EntityItem::somethingChangedNotification(); + _lightPropertiesChanged = false; +} diff --git a/libraries/entities/src/LightEntityItem.h b/libraries/entities/src/LightEntityItem.h index 31ef012f6a..cb23c2357f 100644 --- a/libraries/entities/src/LightEntityItem.h +++ b/libraries/entities/src/LightEntityItem.h @@ -31,9 +31,16 @@ public: /// set dimensions in domain scale units (0.0 - 1.0) this will also reset radius appropriately virtual void setDimensions(const glm::vec3& value) override; + virtual bool setProperties(const EntityItemProperties& properties) override; + virtual bool setSubClassProperties(const EntityItemProperties& properties) override; + // methods for getting/setting all properties of an entity virtual EntityItemProperties getProperties(EntityPropertyFlags desiredProperties = EntityPropertyFlags()) const override; - virtual bool setProperties(const EntityItemProperties& properties) override; + + /// Override this in your derived class if you'd like to be informed when something about the state of the entity + /// has changed. This will be called with properties change or when new data is loaded from a stream + /// Overriding this function to capture the information that a light properties has changed + virtual void somethingChangedNotification() override; virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const override; @@ -60,6 +67,7 @@ public: _color[RED_INDEX] = value.red; _color[GREEN_INDEX] = value.green; _color[BLUE_INDEX] = value.blue; + _lightPropertiesChanged = true; } bool getIsSpotlight() const { return _isSpotlight; } @@ -69,13 +77,19 @@ public: void setIgnoredAttenuation(float value) { } float getIntensity() const { return _intensity; } - void setIntensity(float value) { _intensity = value; } + void setIntensity(float value) { + _intensity = value; + _lightPropertiesChanged = true; + } float getFalloffRadius() const { return _falloffRadius; } void setFalloffRadius(float value); float getExponent() const { return _exponent; } - void setExponent(float value) { _exponent = value; } + void setExponent(float value) { + _exponent = value; + _lightPropertiesChanged = true; + } float getCutoff() const { return _cutoff; } void setCutoff(float value); @@ -85,6 +99,7 @@ public: protected: + // properties of a light rgbColor _color; bool _isSpotlight { DEFAULT_IS_SPOTLIGHT }; @@ -93,6 +108,11 @@ protected: float _exponent { DEFAULT_EXPONENT }; float _cutoff { DEFAULT_CUTOFF }; + // Dirty flag turn true when either light properties is changing values. + // THis gets back to false in the somethingChangedNotification() call + // Which is called after a setProperties() or a readEntitySubClassFromBUfferCall on the entity. + bool _lightPropertiesChanged { false }; + static bool _lightsArePickable; }; diff --git a/libraries/shared/src/shared/NsightHelpers.cpp b/libraries/shared/src/shared/NsightHelpers.cpp index 84fde7887b..9720edd820 100644 --- a/libraries/shared/src/shared/NsightHelpers.cpp +++ b/libraries/shared/src/shared/NsightHelpers.cpp @@ -22,7 +22,8 @@ bool nsightActive() { } ProfileRange::ProfileRange(const char *name) { - _rangeId = nvtxRangeStart(name); + //_rangeId = nvtxRangeStart(name); + _rangeId = nvtxRangePush(name); } ProfileRange::ProfileRange(const char *name, uint32_t argbColor, uint64_t payload) { @@ -36,11 +37,13 @@ ProfileRange::ProfileRange(const char *name, uint32_t argbColor, uint64_t payloa eventAttrib.payload.llValue = payload; eventAttrib.payloadType = NVTX_PAYLOAD_TYPE_UNSIGNED_INT64; - _rangeId = nvtxRangeStartEx(&eventAttrib); + //_rangeId = nvtxRangeStartEx(&eventAttrib); + _rangeId = nvtxRangePushEx(&eventAttrib); } ProfileRange::~ProfileRange() { - nvtxRangeEnd(_rangeId); + // nvtxRangeEnd(_rangeId); + nvtxRangePop(); } #else From 354cbbc92749b056e22ce3e8e4953799aebc0e78 Mon Sep 17 00:00:00 2001 From: samcake Date: Wed, 31 Aug 2016 19:14:35 -0700 Subject: [PATCH 05/75] Investigate why the disable depth Bclamp doesn't work --- .../gpu-gl/src/gpu/gl/GLBackendQuery.cpp | 11 ++++++-- libraries/gpu-gl/src/gpu/gl/GLQuery.h | 1 + libraries/gpu/src/gpu/Query.cpp | 10 ++++--- libraries/gpu/src/gpu/Query.h | 9 +++++-- .../src/AmbientOcclusionEffect.cpp | 10 ++++--- .../render-utils/src/AmbientOcclusionEffect.h | 3 ++- .../src/DeferredLightingEffect.cpp | 21 +++++++++------ .../render-utils/src/DeferredLightingEffect.h | 2 +- .../render-utils/src/RenderDeferredTask.cpp | 14 +++++----- .../render-utils/src/RenderDeferredTask.h | 6 ++--- .../render-utils/src/SurfaceGeometryPass.cpp | 26 ++++++++++++------- .../render-utils/src/SurfaceGeometryPass.h | 4 +-- libraries/render-utils/src/spot_light.slf | 9 +++++-- libraries/shared/src/shared/NsightHelpers.cpp | 22 ++++++++++++++-- libraries/shared/src/shared/NsightHelpers.h | 12 +++++++++ tests/render-perf/src/main.cpp | 2 +- 16 files changed, 115 insertions(+), 47 deletions(-) diff --git a/libraries/gpu-gl/src/gpu/gl/GLBackendQuery.cpp b/libraries/gpu-gl/src/gpu/gl/GLBackendQuery.cpp index 19d008da2c..5fd1c4c6a3 100644 --- a/libraries/gpu-gl/src/gpu/gl/GLBackendQuery.cpp +++ b/libraries/gpu-gl/src/gpu/gl/GLBackendQuery.cpp @@ -25,7 +25,10 @@ void GLBackend::do_beginQuery(const Batch& batch, size_t paramOffset) { auto query = batch._queries.get(batch._params[paramOffset]._uint); GLQuery* glquery = syncGPUObject(*query); if (glquery) { - glGetInteger64v(GL_TIMESTAMP, (GLint64*)&glquery->_batchElapsedTime); + PROFILE_RANGE_BEGIN(glquery->_profileRangeId, query->getName().c_str(), 0xFFFF7F00); + + //glGetInteger64v(GL_TIMESTAMP, (GLint64*)&glquery->_batchElapsedTime); + glquery->_batchElapsedTime = usecTimestampNow() * 1000; if (timeElapsed) { glBeginQuery(GL_TIME_ELAPSED, glquery->_endqo); } else { @@ -45,9 +48,13 @@ void GLBackend::do_endQuery(const Batch& batch, size_t paramOffset) { glQueryCounter(glquery->_endqo, GL_TIMESTAMP); } GLint64 now; - glGetInteger64v(GL_TIMESTAMP, &now); + //glGetInteger64v(GL_TIMESTAMP, &now); + now = usecTimestampNow() * 1000; + glquery->_batchElapsedTime = now - glquery->_batchElapsedTime; + PROFILE_RANGE_END(glquery->_profileRangeId); + (void)CHECK_GL_ERROR(); } } diff --git a/libraries/gpu-gl/src/gpu/gl/GLQuery.h b/libraries/gpu-gl/src/gpu/gl/GLQuery.h index bf10d002e6..1189891967 100644 --- a/libraries/gpu-gl/src/gpu/gl/GLQuery.h +++ b/libraries/gpu-gl/src/gpu/gl/GLQuery.h @@ -49,6 +49,7 @@ public: const GLuint _beginqo = { 0 }; GLuint64 _result { (GLuint64)-1 }; GLuint64 _batchElapsedTime { (GLuint64) 0 }; + uint64_t _profileRangeId { 0 }; protected: GLQuery(const std::weak_ptr& backend, const Query& query, GLuint endId, GLuint beginId) : Parent(backend, query, endId), _beginqo(beginId) {} diff --git a/libraries/gpu/src/gpu/Query.cpp b/libraries/gpu/src/gpu/Query.cpp index 1056193215..38a9d6db8c 100644 --- a/libraries/gpu/src/gpu/Query.cpp +++ b/libraries/gpu/src/gpu/Query.cpp @@ -15,8 +15,9 @@ using namespace gpu; -Query::Query(const Handler& returnHandler) : - _returnHandler(returnHandler) +Query::Query(const Handler& returnHandler, const std::string& name) : + _returnHandler(returnHandler), + _name(name) { } @@ -41,14 +42,15 @@ void Query::triggerReturnHandler(uint64_t queryResult, uint64_t batchElapsedTime } -RangeTimer::RangeTimer() { +RangeTimer::RangeTimer(const std::string& name) : + _name(name) { for (int i = 0; i < QUERY_QUEUE_SIZE; i++) { _timerQueries.push_back(std::make_shared([&, i] (const Query& query) { _tailIndex ++; _movingAverageGPU.addSample(query.getGPUElapsedTime()); _movingAverageBatch.addSample(query.getBatchElapsedTime()); - })); + }, _name)); } } diff --git a/libraries/gpu/src/gpu/Query.h b/libraries/gpu/src/gpu/Query.h index 13b660fc2c..26553d67b3 100644 --- a/libraries/gpu/src/gpu/Query.h +++ b/libraries/gpu/src/gpu/Query.h @@ -15,6 +15,7 @@ #include #include #include +#include #include #include "Format.h" @@ -27,18 +28,21 @@ namespace gpu { public: using Handler = std::function; - Query(const Handler& returnHandler); + Query(const Handler& returnHandler, const std::string& name = "gpu::query"); ~Query(); double getGPUElapsedTime() const; double getBatchElapsedTime() const; + const std::string& getName() const { return _name; } + // Only for gpu::Context const GPUObjectPointer gpuObject {}; void triggerReturnHandler(uint64_t queryResult, uint64_t batchElapsedTime); protected: Handler _returnHandler; + std::string _name; uint64_t _queryResult { 0 }; uint64_t _usecBatchElapsedTime { 0 }; }; @@ -52,7 +56,7 @@ namespace gpu { // The result is always a late average of the time spent for that same task a few cycles ago. class RangeTimer { public: - RangeTimer(); + RangeTimer(const std::string& name); void begin(gpu::Batch& batch); void end(gpu::Batch& batch); @@ -63,6 +67,7 @@ namespace gpu { static const int QUERY_QUEUE_SIZE { 4 }; + std::string _name; gpu::Queries _timerQueries; int _headIndex = -1; int _tailIndex = -1; diff --git a/libraries/render-utils/src/AmbientOcclusionEffect.cpp b/libraries/render-utils/src/AmbientOcclusionEffect.cpp index 3bf887e1b6..61a8c1f994 100644 --- a/libraries/render-utils/src/AmbientOcclusionEffect.cpp +++ b/libraries/render-utils/src/AmbientOcclusionEffect.cpp @@ -351,6 +351,10 @@ void AmbientOcclusionEffect::run(const render::SceneContextPointer& sceneContext auto sourceViewport = args->_viewport; auto occlusionViewport = sourceViewport; + if (!_gpuTimer) { + _gpuTimer = std::make_shared < gpu::RangeTimer>(__FUNCTION__); + } + if (!_framebuffer) { _framebuffer = std::make_shared(); } @@ -384,7 +388,7 @@ void AmbientOcclusionEffect::run(const render::SceneContextPointer& sceneContext gpu::doInBatch(args->_context, [=](gpu::Batch& batch) { batch.enableStereo(false); - _gpuTimer.begin(batch); + _gpuTimer->begin(batch); batch.setViewportTransform(occlusionViewport); batch.setProjectionTransform(glm::mat4()); @@ -428,12 +432,12 @@ void AmbientOcclusionEffect::run(const render::SceneContextPointer& sceneContext batch.setResourceTexture(AmbientOcclusionEffect_LinearDepthMapSlot, nullptr); batch.setResourceTexture(AmbientOcclusionEffect_OcclusionMapSlot, nullptr); - _gpuTimer.end(batch); + _gpuTimer->end(batch); }); // Update the timer auto config = std::static_pointer_cast(renderContext->jobConfig); - config->setGPUBatchRunTime(_gpuTimer.getGPUAverage(), _gpuTimer.getBatchAverage()); + config->setGPUBatchRunTime(_gpuTimer->getGPUAverage(), _gpuTimer->getBatchAverage()); } diff --git a/libraries/render-utils/src/AmbientOcclusionEffect.h b/libraries/render-utils/src/AmbientOcclusionEffect.h index 1a828cb2c0..80904c80a3 100644 --- a/libraries/render-utils/src/AmbientOcclusionEffect.h +++ b/libraries/render-utils/src/AmbientOcclusionEffect.h @@ -12,6 +12,7 @@ #ifndef hifi_AmbientOcclusionEffect_h #define hifi_AmbientOcclusionEffect_h +#include #include #include "render/DrawTask.h" @@ -188,7 +189,7 @@ private: AmbientOcclusionFramebufferPointer _framebuffer; - gpu::RangeTimer _gpuTimer; + gpu::RangeTimerPointer _gpuTimer; friend class DebugAmbientOcclusion; }; diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index c158d6c180..0f09d7ee4f 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -219,8 +219,9 @@ static void loadLightProgram(const char* vertSource, const char* fragSource, boo if (lightVolume) { state->setCullMode(gpu::State::CULL_BACK); - state->setDepthTest(true, false, gpu::LESS_EQUAL); + state->setDepthTest(true, true, gpu::LESS_EQUAL); + state->setDepthClampEnable(true); // TODO: We should use DepthClamp and avoid changing geometry for inside /outside cases // additive blending state->setBlendFunction(true, gpu::State::ONE, gpu::State::BLEND_OP_ADD, gpu::State::ONE); @@ -598,11 +599,11 @@ void RenderDeferredLocals::run(const render::SceneContextPointer& sceneContext, // TODO: We shouldn;t have to do that test and use a different volume geometry for when inside the vlight volume, // we should be able to draw thre same geometry use DepthClamp but for unknown reason it's s not working... - if (glm::distance(eyePoint, glm::vec3(light->getPosition())) < expandedRadius + nearRadius) { + /* if (glm::distance(eyePoint, glm::vec3(light->getPosition())) < expandedRadius + nearRadius) { sphereParam.w = 0.0f; batch._glUniform4fv(deferredLightingEffect->_pointLightLocations->sphereParam, 1, reinterpret_cast< const float* >(&sphereParam)); batch.draw(gpu::TRIANGLE_STRIP, 4); - } else { + } else*/ { sphereParam.w = 1.0f; batch._glUniform4fv(deferredLightingEffect->_pointLightLocations->sphereParam, 1, reinterpret_cast< const float* >(&sphereParam)); @@ -647,12 +648,12 @@ void RenderDeferredLocals::run(const render::SceneContextPointer& sceneContext, // TODO: We shouldn;t have to do that test and use a different volume geometry for when inside the vlight volume, // we should be able to draw thre same geometry use DepthClamp but for unknown reason it's s not working... const float OVER_CONSERVATIVE_SCALE = 1.1f; - if ((eyeHalfPlaneDistance > -nearRadius) && + /* if ((eyeHalfPlaneDistance > -nearRadius) && (glm::distance(eyePoint, glm::vec3(light->getPosition())) < (expandedRadius * OVER_CONSERVATIVE_SCALE) + nearRadius)) { coneParam.w = 0.0f; batch._glUniform4fv(deferredLightingEffect->_spotLightLocations->coneParam, 1, reinterpret_cast< const float* >(&coneParam)); batch.draw(gpu::TRIANGLE_STRIP, 4); - } else { + } else*/ { coneParam.w = 1.0f; batch._glUniform4fv(deferredLightingEffect->_spotLightLocations->coneParam, 1, reinterpret_cast< const float* >(&coneParam)); @@ -720,8 +721,12 @@ void RenderDeferred::run(const SceneContextPointer& sceneContext, const RenderCo auto subsurfaceScatteringResource = inputs.get5(); auto args = renderContext->args; + if (!_gpuTimer) { + _gpuTimer = std::make_shared < gpu::RangeTimer>(__FUNCTION__); + } + gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { - _gpuTimer.begin(batch); + _gpuTimer->begin(batch); }); setupJob.run(sceneContext, renderContext, deferredTransform, deferredFramebuffer, lightingModel, surfaceGeometryFramebuffer, ssaoFramebuffer, subsurfaceScatteringResource); @@ -731,9 +736,9 @@ void RenderDeferred::run(const SceneContextPointer& sceneContext, const RenderCo cleanupJob.run(sceneContext, renderContext); gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { - _gpuTimer.end(batch); + _gpuTimer->end(batch); }); auto config = std::static_pointer_cast(renderContext->jobConfig); - config->setGPUBatchRunTime(_gpuTimer.getGPUAverage(), _gpuTimer.getBatchAverage()); + config->setGPUBatchRunTime(_gpuTimer->getGPUAverage(), _gpuTimer->getBatchAverage()); } diff --git a/libraries/render-utils/src/DeferredLightingEffect.h b/libraries/render-utils/src/DeferredLightingEffect.h index e4f3f455fa..ff0db1330f 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.h +++ b/libraries/render-utils/src/DeferredLightingEffect.h @@ -183,7 +183,7 @@ public: RenderDeferredCleanup cleanupJob; protected: - gpu::RangeTimer _gpuTimer; + gpu::RangeTimerPointer _gpuTimer; }; #endif // hifi_DeferredLightingEffect_h diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 1e63cba8da..32aa2b6e16 100755 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -101,7 +101,7 @@ RenderDeferredTask::RenderDeferredTask(CullFunctor cullFunctor) { const auto primaryFramebuffer = addJob("PreparePrimaryBuffer"); // const auto fullFrameRangeTimer = addJob("BeginRangeTimer"); - const auto opaqueRangeTimer = addJob("BeginOpaqueRangeTimer"); + const auto opaqueRangeTimer = addJob("BeginOpaqueRangeTimer", "DrawOpaques"); const auto prepareDeferredInputs = PrepareDeferred::Inputs(primaryFramebuffer, lightingModel).hasVarying(); const auto prepareDeferredOutputs = addJob("PrepareDeferred", prepareDeferredInputs); @@ -146,8 +146,8 @@ RenderDeferredTask::RenderDeferredTask(CullFunctor cullFunctor) { addJob("DrawLight", lights); const auto deferredLightingInputs = RenderDeferred::Inputs(deferredFrameTransform, deferredFramebuffer, lightingModel, - surfaceGeometryFramebuffer, ambientOcclusionFramebuffer, scatteringResource).hasVarying(); - + surfaceGeometryFramebuffer, ambientOcclusionFramebuffer, scatteringResource).hasVarying(); + // DeferredBuffer is complete, now let's shade it into the LightingBuffer addJob("RenderDeferred", deferredLightingInputs); @@ -159,7 +159,7 @@ RenderDeferredTask::RenderDeferredTask(CullFunctor cullFunctor) { const auto transparentsInputs = DrawDeferred::Inputs(transparents, lightingModel).hasVarying(); addJob("DrawTransparentDeferred", transparentsInputs, shapePlumber); - const auto toneAndPostRangeTimer = addJob("BeginToneAndPostRangeTimer"); + const auto toneAndPostRangeTimer = addJob("BeginToneAndPostRangeTimer", "PostToneOverlaysAntialiasing"); // Lighting Buffer ready for tone mapping const auto toneMappingInputs = render::Varying(ToneMappingDeferred::Inputs(lightingFramebuffer, primaryFramebuffer)); @@ -174,9 +174,9 @@ RenderDeferredTask::RenderDeferredTask(CullFunctor cullFunctor) { // Debugging stages { - // Debugging Deferred buffer job - const auto debugFramebuffers = render::Varying(DebugDeferredBuffer::Inputs(deferredFramebuffer, linearDepthTarget, surfaceGeometryFramebuffer, ambientOcclusionFramebuffer)); - addJob("DebugDeferredBuffer", debugFramebuffers); + // Debugging Deferred buffer job + const auto debugFramebuffers = render::Varying(DebugDeferredBuffer::Inputs(deferredFramebuffer, linearDepthTarget, surfaceGeometryFramebuffer, ambientOcclusionFramebuffer)); + addJob("DebugDeferredBuffer", debugFramebuffers); addJob("DebugScattering", deferredLightingInputs); diff --git a/libraries/render-utils/src/RenderDeferredTask.h b/libraries/render-utils/src/RenderDeferredTask.h index e379e42445..fb15e34569 100755 --- a/libraries/render-utils/src/RenderDeferredTask.h +++ b/libraries/render-utils/src/RenderDeferredTask.h @@ -21,7 +21,7 @@ class BeginGPURangeTimer { public: using JobModel = render::Job::ModelO; - BeginGPURangeTimer() : _gpuTimer(std::make_shared()) {} + BeginGPURangeTimer(const std::string& name) : _gpuTimer(std::make_shared(name)) {} void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext, gpu::RangeTimerPointer& timer); @@ -146,7 +146,7 @@ public: void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext, const Inputs& inputs); protected: - gpu::RangeTimer _gpuTimer; + gpu::RangeTimerPointer _gpuTimer; }; class DrawOverlay3DConfig : public render::Job::Config { @@ -205,7 +205,7 @@ public: using JobModel = Model; protected: - gpu::RangeTimer _gpuTimer; + gpu::RangeTimerPointer _gpuTimer; }; #endif // hifi_RenderDeferredTask_h diff --git a/libraries/render-utils/src/SurfaceGeometryPass.cpp b/libraries/render-utils/src/SurfaceGeometryPass.cpp index 1957f8456a..70ada8b4a0 100644 --- a/libraries/render-utils/src/SurfaceGeometryPass.cpp +++ b/libraries/render-utils/src/SurfaceGeometryPass.cpp @@ -61,9 +61,9 @@ void LinearDepthFramebuffer::updatePrimaryDepth(const gpu::TexturePointer& depth void LinearDepthFramebuffer::clear() { _linearDepthFramebuffer.reset(); _linearDepthTexture.reset(); - _downsampleFramebuffer.reset(); - _halfLinearDepthTexture.reset(); - _halfNormalTexture.reset(); + _downsampleFramebuffer.reset(); + _halfLinearDepthTexture.reset(); + _halfNormalTexture.reset(); } void LinearDepthFramebuffer::allocate() { @@ -142,6 +142,10 @@ void LinearDepthPass::run(const render::SceneContextPointer& sceneContext, const const auto frameTransform = inputs.get0(); const auto deferredFramebuffer = inputs.get1(); + if (!_gpuTimer) { + _gpuTimer = std::make_shared < gpu::RangeTimer>(__FUNCTION__); + } + if (!_linearDepthFramebuffer) { _linearDepthFramebuffer = std::make_shared(); } @@ -171,7 +175,7 @@ void LinearDepthPass::run(const render::SceneContextPointer& sceneContext, const float clearLinearDepth = args->getViewFrustum().getFarClip() * 2.0f; gpu::doInBatch(args->_context, [=](gpu::Batch& batch) { - _gpuTimer.begin(batch); + _gpuTimer->begin(batch); batch.enableStereo(false); batch.setViewportTransform(depthViewport); @@ -197,11 +201,11 @@ void LinearDepthPass::run(const render::SceneContextPointer& sceneContext, const batch.setPipeline(downsamplePipeline); batch.draw(gpu::TRIANGLE_STRIP, 4); - _gpuTimer.end(batch); + _gpuTimer->end(batch); }); auto config = std::static_pointer_cast(renderContext->jobConfig); - config->setGPUBatchRunTime(_gpuTimer.getGPUAverage(), _gpuTimer.getBatchAverage()); + config->setGPUBatchRunTime(_gpuTimer->getGPUAverage(), _gpuTimer->getBatchAverage()); } @@ -406,6 +410,10 @@ void SurfaceGeometryPass::run(const render::SceneContextPointer& sceneContext, c RenderArgs* args = renderContext->args; + if (!_gpuTimer) { + _gpuTimer = std::make_shared < gpu::RangeTimer>(__FUNCTION__); + } + const auto frameTransform = inputs.get0(); const auto deferredFramebuffer = inputs.get1(); const auto linearDepthFramebuffer = inputs.get2(); @@ -458,7 +466,7 @@ void SurfaceGeometryPass::run(const render::SceneContextPointer& sceneContext, c gpu::doInBatch(args->_context, [=](gpu::Batch& batch) { - _gpuTimer.begin(batch); + _gpuTimer->begin(batch); batch.enableStereo(false); batch.setProjectionTransform(glm::mat4()); @@ -519,12 +527,12 @@ void SurfaceGeometryPass::run(const render::SceneContextPointer& sceneContext, c batch.setResourceTexture(BlurTask_DepthSlot, nullptr); batch.setUniformBuffer(BlurTask_ParamsSlot, nullptr); - _gpuTimer.end(batch); + _gpuTimer->end(batch); }); auto config = std::static_pointer_cast(renderContext->jobConfig); - config->setGPUBatchRunTime(_gpuTimer.getGPUAverage(), _gpuTimer.getBatchAverage()); + config->setGPUBatchRunTime(_gpuTimer->getGPUAverage(), _gpuTimer->getBatchAverage()); } diff --git a/libraries/render-utils/src/SurfaceGeometryPass.h b/libraries/render-utils/src/SurfaceGeometryPass.h index 3bc6b45c7c..6d830f9a28 100644 --- a/libraries/render-utils/src/SurfaceGeometryPass.h +++ b/libraries/render-utils/src/SurfaceGeometryPass.h @@ -87,7 +87,7 @@ private: const gpu::PipelinePointer& getDownsamplePipeline(); gpu::PipelinePointer _downsamplePipeline; - gpu::RangeTimer _gpuTimer; + gpu::RangeTimerPointer _gpuTimer; }; @@ -202,7 +202,7 @@ private: render::BlurGaussianDepthAware _diffusePass; - gpu::RangeTimer _gpuTimer; + gpu::RangeTimerPointer _gpuTimer; }; #endif // hifi_SurfaceGeometryPass_h diff --git a/libraries/render-utils/src/spot_light.slf b/libraries/render-utils/src/spot_light.slf index 4d4ad71413..0aa56947f7 100644 --- a/libraries/render-utils/src/spot_light.slf +++ b/libraries/render-utils/src/spot_light.slf @@ -31,14 +31,14 @@ in vec4 _texCoord0; out vec4 _fragColor; void main(void) { - + _fragColor = vec4(1.0, 0.0, 0.0, 1.0);// + return; DeferredFrameTransform deferredTransform = getDeferredFrameTransform(); // Grab the fragment data from the uv vec2 texCoord = _texCoord0.st / _texCoord0.q; texCoord *= texcoordFrameTransform.zw; texCoord += texcoordFrameTransform.xy; - DeferredFragment frag = unpackDeferredFragment(deferredTransform, texCoord); if (frag.mode == FRAG_MODE_UNLIT) { @@ -66,6 +66,11 @@ void main(void) { discard; } + + + + + // Frag to eye vec vec4 fragEyeVector = invViewMat * vec4(-frag.position.xyz, 0.0); vec3 fragEyeDir = normalize(fragEyeVector.xyz); diff --git a/libraries/shared/src/shared/NsightHelpers.cpp b/libraries/shared/src/shared/NsightHelpers.cpp index 9720edd820..fa853029be 100644 --- a/libraries/shared/src/shared/NsightHelpers.cpp +++ b/libraries/shared/src/shared/NsightHelpers.cpp @@ -21,8 +21,26 @@ bool nsightActive() { return nsightLaunched; } + +uint64_t ProfileRange::beginRange(const char* name, uint32_t argbColor) { + nvtxEventAttributes_t eventAttrib = { 0 }; + eventAttrib.version = NVTX_VERSION; + eventAttrib.size = NVTX_EVENT_ATTRIB_STRUCT_SIZE; + eventAttrib.colorType = NVTX_COLOR_ARGB; + eventAttrib.color = argbColor; + eventAttrib.messageType = NVTX_MESSAGE_TYPE_ASCII; + eventAttrib.message.ascii = name; + return nvtxRangeStartEx(&eventAttrib); + // return nvtxRangePushEx(&eventAttrib); +} + +void ProfileRange::endRange(uint64_t rangeId) { + nvtxRangeEnd(rangeId); + // nvtxRangePop(); +} + ProfileRange::ProfileRange(const char *name) { - //_rangeId = nvtxRangeStart(name); + // _rangeId = nvtxRangeStart(name); _rangeId = nvtxRangePush(name); } @@ -42,7 +60,7 @@ ProfileRange::ProfileRange(const char *name, uint32_t argbColor, uint64_t payloa } ProfileRange::~ProfileRange() { - // nvtxRangeEnd(_rangeId); + // nvtxRangeEnd(_rangeId); nvtxRangePop(); } diff --git a/libraries/shared/src/shared/NsightHelpers.h b/libraries/shared/src/shared/NsightHelpers.h index 94cb8d5263..294ffe0f7d 100644 --- a/libraries/shared/src/shared/NsightHelpers.h +++ b/libraries/shared/src/shared/NsightHelpers.h @@ -19,15 +19,27 @@ public: ProfileRange(const char *name); ProfileRange(const char *name, uint32_t argbColor, uint64_t payload); ~ProfileRange(); + + static uint64_t beginRange(const char* name, uint32_t argbColor); + static void endRange(uint64_t rangeId); private: uint64_t _rangeId{ 0 }; }; #define PROFILE_RANGE(name) ProfileRange profileRangeThis(name); #define PROFILE_RANGE_EX(name, argbColor, payload) ProfileRange profileRangeThis(name, argbColor, (uint64_t)payload); + +#define PROFILE_RANGE_BEGIN(rangeId, name, argbColor) rangeId = ProfileRange::beginRange(name, argbColor) +#define PROFILE_RANGE_END(rangeId) ProfileRange::endRange(rangeId) + #else #define PROFILE_RANGE(name) #define PROFILE_RANGE_EX(name, argbColor, payload) + + +#define PROFILE_RANGE_BEGIN(rangeId, name, argbColor) +#define PROFILE_RANGE_END(rangeId) + #endif #endif diff --git a/tests/render-perf/src/main.cpp b/tests/render-perf/src/main.cpp index c6cca74c69..030a39a1cd 100644 --- a/tests/render-perf/src/main.cpp +++ b/tests/render-perf/src/main.cpp @@ -526,7 +526,7 @@ public: _octree->init(); // Prevent web entities from rendering REGISTER_ENTITY_TYPE_WITH_FACTORY(Web, WebEntityItem::factory); - REGISTER_ENTITY_TYPE_WITH_FACTORY(Light, LightEntityItem::factory); +// REGISTER_ENTITY_TYPE_WITH_FACTORY(Light, LightEntityItem::factory); DependencyManager::set(_octree->getTree()); getEntities()->setViewFrustum(_viewFrustum); From a537f40158346e1737ce7c37688003bdfcc16ad3 Mon Sep 17 00:00:00 2001 From: samcake Date: Thu, 1 Sep 2016 12:10:15 -0700 Subject: [PATCH 06/75] Moving to a simpler lighting shader --- libraries/render-utils/src/DeferredLightingEffect.cpp | 6 +++--- libraries/render-utils/src/point_light.slf | 4 ++-- libraries/render-utils/src/spot_light.slf | 8 ++++---- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index 0f09d7ee4f..df80065ff5 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -218,10 +218,10 @@ static void loadLightProgram(const char* vertSource, const char* fragSource, boo state->setStencilTest(true, 0xFF, gpu::State::StencilTest(0, 0xFF, gpu::NOT_EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP)); if (lightVolume) { - state->setCullMode(gpu::State::CULL_BACK); - state->setDepthTest(true, true, gpu::LESS_EQUAL); + state->setCullMode(gpu::State::CULL_FRONT); + state->setDepthTest(true, false, gpu::GREATER_EQUAL); - state->setDepthClampEnable(true); + //state->setDepthClampEnable(true); // TODO: We should use DepthClamp and avoid changing geometry for inside /outside cases // additive blending state->setBlendFunction(true, gpu::State::ONE, gpu::State::BLEND_OP_ADD, gpu::State::ONE); diff --git a/libraries/render-utils/src/point_light.slf b/libraries/render-utils/src/point_light.slf index 80b2e62b8a..b92f18255c 100644 --- a/libraries/render-utils/src/point_light.slf +++ b/libraries/render-utils/src/point_light.slf @@ -46,10 +46,10 @@ void main(void) { } // Kill if in front of the light volume - float depth = frag.depthVal; +/* float depth = frag.depthVal; if (depth < gl_FragCoord.z) { discard; - } + }*/ // Need the light now Light light = getLight(); diff --git a/libraries/render-utils/src/spot_light.slf b/libraries/render-utils/src/spot_light.slf index 0aa56947f7..058e0dadea 100644 --- a/libraries/render-utils/src/spot_light.slf +++ b/libraries/render-utils/src/spot_light.slf @@ -31,8 +31,8 @@ in vec4 _texCoord0; out vec4 _fragColor; void main(void) { - _fragColor = vec4(1.0, 0.0, 0.0, 1.0);// - return; + /* _fragColor = vec4(1.0, 0.0, 0.0, 1.0);// + return;*/ DeferredFrameTransform deferredTransform = getDeferredFrameTransform(); // Grab the fragment data from the uv @@ -47,9 +47,9 @@ void main(void) { // Kill if in front of the light volume float depth = frag.depthVal; - if (depth < gl_FragCoord.z) { + /* if (depth < gl_FragCoord.z) { discard; - } + }*/ // Need the light now Light light = getLight(); From 96935504a14cb48779812bae7d646a709caaf892 Mon Sep 17 00:00:00 2001 From: samcake Date: Thu, 1 Sep 2016 15:20:14 -0700 Subject: [PATCH 07/75] Streamlining the lighting phase for better performances --- libraries/model/src/model/Light.cpp | 22 ++++++++++++++ libraries/model/src/model/Light.h | 7 ++++- libraries/model/src/model/Light.slh | 6 ++++ .../src/DeferredLightingEffect.cpp | 20 ++++++------- .../src/deferred_light_limited.slv | 29 +++++-------------- .../render-utils/src/deferred_light_spot.slv | 11 ++++--- libraries/render-utils/src/point_light.slf | 6 ---- libraries/render-utils/src/spot_light.slf | 13 --------- 8 files changed, 59 insertions(+), 55 deletions(-) diff --git a/libraries/model/src/model/Light.cpp b/libraries/model/src/model/Light.cpp index 1762b0a9fb..4421864569 100755 --- a/libraries/model/src/model/Light.cpp +++ b/libraries/model/src/model/Light.cpp @@ -37,6 +37,13 @@ Light& Light::operator= (const Light& light) { Light::~Light() { } +void Light::setType(Type type) { + editSchema()._control.x = float(type); + updateLightRadius(); + updateVolumeGeometry(); +} + + void Light::setPosition(const Vec3& position) { _transform.setTranslation(position); editSchema()._position = Vec4(position, 1.f); @@ -82,6 +89,7 @@ void Light::setMaximumRadius(float radius) { } editSchema()._attenuation.y = radius; updateLightRadius(); + updateVolumeGeometry(); } void Light::updateLightRadius() { @@ -117,6 +125,8 @@ void Light::setSpotAngle(float angle) { editSchema()._spot.x = (float) std::abs(cosAngle); editSchema()._spot.y = (float) std::abs(sinAngle); editSchema()._spot.z = (float) angle; + + updateVolumeGeometry(); } void Light::setSpotExponent(float exponent) { @@ -153,3 +163,15 @@ void Light::setAmbientMap(gpu::TexturePointer ambientMap) { void Light::setAmbientMapNumMips(uint16_t numMips) { editSchema()._ambientMapNumMips = (float)numMips; } + +void Light::updateVolumeGeometry() { + // enlarge the scales slightly to account for tesselation + const float SCALE_EXPANSION = 0.05f; + glm::vec4 volumeGeometry(0.0f, 0.0f, 0.0f, 1.0f); // getMaximumRadius() * (1.0f + SCALE_EXPANSION)); + + if (getType() == SPOT) { + const float TANGENT_LENGTH_SCALE = 0.666f; + volumeGeometry = glm::vec4(getSpotAngleCosSin(), TANGENT_LENGTH_SCALE * tanf(0.5f * getSpotAngle()), volumeGeometry.w); + } + editSchema()._volumeGeometry = volumeGeometry; +} diff --git a/libraries/model/src/model/Light.h b/libraries/model/src/model/Light.h index 3b320e08fd..058d4d4741 100755 --- a/libraries/model/src/model/Light.h +++ b/libraries/model/src/model/Light.h @@ -54,7 +54,7 @@ public: Light& operator= (const Light& light); virtual ~Light(); - void setType(Type type) { editSchema()._control.x = float(type); } + void setType(Type type); Type getType() const { return Type((int) getSchema()._control.x); } void setPosition(const Vec3& position); @@ -126,9 +126,12 @@ public: Vec4 _spot{0.0f, 0.0f, 0.0f, 0.0f}; Vec4 _shadow{0.0f}; + float _ambientMapNumMips{ 0.0f }; Vec3 _control{ 0.0f, 0.0f, 0.0f }; + Vec4 _volumeGeometry { 1.f }; + gpu::SphericalHarmonics _ambientSphere; }; @@ -146,6 +149,8 @@ protected: Schema& editSchema() { return _schemaBuffer.edit(); } void updateLightRadius(); + void updateVolumeGeometry(); + }; typedef std::shared_ptr< Light > LightPointer; diff --git a/libraries/model/src/model/Light.slh b/libraries/model/src/model/Light.slh index 5e9d3d30c0..de2ca97088 100644 --- a/libraries/model/src/model/Light.slh +++ b/libraries/model/src/model/Light.slh @@ -56,6 +56,8 @@ struct Light { vec4 _shadow; vec4 _control; + vec4 _volumeGeometry; + SphericalHarmonics _ambientSphere; }; @@ -98,6 +100,10 @@ float getLightShowContour(Light l) { return l._control.w; } +vec4 getLightVolumeGeometry(Light l) { + return l._volumeGeometry; +} + // Light is the light source its self, d is the light's distance calculated as length(unnormalized light vector). float evalLightAttenuation(Light l, float d) { float radius = getLightRadius(l); diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index df80065ff5..af98422b92 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -594,18 +594,18 @@ void RenderDeferredLocals::run(const render::SceneContextPointer& sceneContext, // IN DEBUG: light->setShowContour(true); batch.setUniformBuffer(deferredLightingEffect->_pointLightLocations->lightBufferUnit, light->getSchemaBuffer()); - float expandedRadius = light->getMaximumRadius() * (1.0f + SCALE_EXPANSION); - glm::vec4 sphereParam(expandedRadius, 0.0f, 0.0f, 1.0f); + float expandedRadius = light->getMaximumRadius() * (1.0f + SCALE_EXPANSION); + // glm::vec4 sphereParam(expandedRadius, 0.0f, 0.0f, 1.0f); // TODO: We shouldn;t have to do that test and use a different volume geometry for when inside the vlight volume, // we should be able to draw thre same geometry use DepthClamp but for unknown reason it's s not working... - /* if (glm::distance(eyePoint, glm::vec3(light->getPosition())) < expandedRadius + nearRadius) { + /* if (glm::distance(eyePoint, glm::vec3(light->getPosition())) < expandedRadius + nearRadius) { sphereParam.w = 0.0f; batch._glUniform4fv(deferredLightingEffect->_pointLightLocations->sphereParam, 1, reinterpret_cast< const float* >(&sphereParam)); batch.draw(gpu::TRIANGLE_STRIP, 4); } else*/ { - sphereParam.w = 1.0f; - batch._glUniform4fv(deferredLightingEffect->_pointLightLocations->sphereParam, 1, reinterpret_cast< const float* >(&sphereParam)); + // sphereParam.w = 1.0f; + // batch._glUniform4fv(deferredLightingEffect->_pointLightLocations->sphereParam, 1, reinterpret_cast< const float* >(&sphereParam)); Transform model; model.setTranslation(glm::vec3(light->getPosition().x, light->getPosition().y, light->getPosition().z)); @@ -638,7 +638,7 @@ void RenderDeferredLocals::run(const render::SceneContextPointer& sceneContext, // light->setShowContour(true); batch.setUniformBuffer(deferredLightingEffect->_spotLightLocations->lightBufferUnit, light->getSchemaBuffer()); - auto eyeLightPos = eyePoint - light->getPosition(); + /* auto eyeLightPos = eyePoint - light->getPosition(); auto eyeHalfPlaneDistance = glm::dot(eyeLightPos, light->getDirection()); const float TANGENT_LENGTH_SCALE = 0.666f; @@ -648,19 +648,19 @@ void RenderDeferredLocals::run(const render::SceneContextPointer& sceneContext, // TODO: We shouldn;t have to do that test and use a different volume geometry for when inside the vlight volume, // we should be able to draw thre same geometry use DepthClamp but for unknown reason it's s not working... const float OVER_CONSERVATIVE_SCALE = 1.1f; - /* if ((eyeHalfPlaneDistance > -nearRadius) && + if ((eyeHalfPlaneDistance > -nearRadius) && (glm::distance(eyePoint, glm::vec3(light->getPosition())) < (expandedRadius * OVER_CONSERVATIVE_SCALE) + nearRadius)) { coneParam.w = 0.0f; batch._glUniform4fv(deferredLightingEffect->_spotLightLocations->coneParam, 1, reinterpret_cast< const float* >(&coneParam)); batch.draw(gpu::TRIANGLE_STRIP, 4); } else*/ { - coneParam.w = 1.0f; - batch._glUniform4fv(deferredLightingEffect->_spotLightLocations->coneParam, 1, reinterpret_cast< const float* >(&coneParam)); + // coneParam.w = 1.0f; + // batch._glUniform4fv(deferredLightingEffect->_spotLightLocations->coneParam, 1, reinterpret_cast< const float* >(&coneParam)); Transform model; model.setTranslation(light->getPosition()); model.postRotate(light->getOrientation()); - model.postScale(glm::vec3(expandedRadius, expandedRadius, expandedRadius)); + // model.postScale(glm::vec3(expandedRadius, expandedRadius, expandedRadius)); batch.setModelTransform(model); diff --git a/libraries/render-utils/src/deferred_light_limited.slv b/libraries/render-utils/src/deferred_light_limited.slv index 81ec882bdf..7168d5386d 100644 --- a/libraries/render-utils/src/deferred_light_limited.slv +++ b/libraries/render-utils/src/deferred_light_limited.slv @@ -18,17 +18,21 @@ <$declareStandardTransform()$> -uniform vec4 sphereParam; +!> + out vec4 _texCoord0; void main(void) { - if (sphereParam.w != 0.0) { + vec4 sphereVertex = inPosition; + // vec4 sphereParam = getLightVolumeGeometry(getLight()); - // standard transform + // sphereVertex.xyz *= sphereParam.w; + + // standard transform TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); - <$transformModelToClipPos(cam, obj, inPosition, gl_Position)$>; + <$transformModelToClipPos(cam, obj, sphereVertex, gl_Position)$>; vec4 projected = gl_Position / gl_Position.w; projected.xy = (projected.xy + 1.0) * 0.5; @@ -37,21 +41,4 @@ void main(void) { projected.x = 0.5 * (projected.x + cam_getStereoSide()); } _texCoord0 = vec4(projected.xy, 0.0, 1.0) * gl_Position.w; - } else { - const float depth = -1.0; //Draw at near plane - const vec4 UNIT_QUAD[4] = vec4[4]( - vec4(-1.0, -1.0, depth, 1.0), - vec4(1.0, -1.0, depth, 1.0), - vec4(-1.0, 1.0, depth, 1.0), - vec4(1.0, 1.0, depth, 1.0) - ); - vec4 pos = UNIT_QUAD[gl_VertexID]; - - _texCoord0 = vec4((pos.xy + 1) * 0.5, 0.0, 1.0); - - if (cam_isStereo()) { - _texCoord0.x = 0.5 * (_texCoord0.x + cam_getStereoSide()); - } - gl_Position = pos; - } } diff --git a/libraries/render-utils/src/deferred_light_spot.slv b/libraries/render-utils/src/deferred_light_spot.slv index 6ae133b7a5..e48f8ba907 100755 --- a/libraries/render-utils/src/deferred_light_spot.slv +++ b/libraries/render-utils/src/deferred_light_spot.slv @@ -18,13 +18,15 @@ <$declareStandardTransform()$> -uniform vec4 coneParam; +<@include model/Light.slh@> + out vec4 _texCoord0; void main(void) { vec4 coneVertex = inPosition; - if (coneParam.w != 0.0) { + // if (coneParam.w != 0.0) { + vec4 coneParam = getLightVolumeGeometry(getLight()); if(coneVertex.z >= 0.0) { // Evaluate the true position of the spot volume vec2 dir = float(coneVertex.z < 0.5f) * (coneParam.xy @@ -38,6 +40,7 @@ void main(void) { coneVertex.z = 0.0; } + coneVertex.xyz *= coneParam.w; // standard transform TransformCamera cam = getTransformCamera(); @@ -50,7 +53,7 @@ void main(void) { projected.x = 0.5 * (projected.x + cam_getStereoSide()); } _texCoord0 = vec4(projected.xy, 0.0, 1.0) * gl_Position.w; - } else { + /* } else { const float depth = -1.0; //Draw at near plane const vec4 UNIT_QUAD[4] = vec4[4]( vec4(-1.0, -1.0, depth, 1.0), @@ -65,5 +68,5 @@ void main(void) { _texCoord0.x = 0.5 * (_texCoord0.x + cam_getStereoSide()); } gl_Position = pos; - } + }*/ } diff --git a/libraries/render-utils/src/point_light.slf b/libraries/render-utils/src/point_light.slf index b92f18255c..6aab2489be 100644 --- a/libraries/render-utils/src/point_light.slf +++ b/libraries/render-utils/src/point_light.slf @@ -45,12 +45,6 @@ void main(void) { discard; } - // Kill if in front of the light volume -/* float depth = frag.depthVal; - if (depth < gl_FragCoord.z) { - discard; - }*/ - // Need the light now Light light = getLight(); diff --git a/libraries/render-utils/src/spot_light.slf b/libraries/render-utils/src/spot_light.slf index 058e0dadea..c2d99259db 100644 --- a/libraries/render-utils/src/spot_light.slf +++ b/libraries/render-utils/src/spot_light.slf @@ -31,8 +31,6 @@ in vec4 _texCoord0; out vec4 _fragColor; void main(void) { - /* _fragColor = vec4(1.0, 0.0, 0.0, 1.0);// - return;*/ DeferredFrameTransform deferredTransform = getDeferredFrameTransform(); // Grab the fragment data from the uv @@ -45,12 +43,6 @@ void main(void) { discard; } - // Kill if in front of the light volume - float depth = frag.depthVal; - /* if (depth < gl_FragCoord.z) { - discard; - }*/ - // Need the light now Light light = getLight(); @@ -66,11 +58,6 @@ void main(void) { discard; } - - - - - // Frag to eye vec vec4 fragEyeVector = invViewMat * vec4(-frag.position.xyz, 0.0); vec3 fragEyeDir = normalize(fragEyeVector.xyz); From e72791233db1fd200ecee452bc99b34b4276101f Mon Sep 17 00:00:00 2001 From: samcake Date: Thu, 1 Sep 2016 18:08:36 -0700 Subject: [PATCH 08/75] overall clean up of th elocal light drawing to avoid the in/out pipeline case, still seeing big cost on gpu from the spot lights --- libraries/model/src/model/Light.cpp | 2 +- .../src/DeferredLightingEffect.cpp | 130 +++++++++--------- .../render-utils/src/DeferredLightingEffect.h | 2 + libraries/render-utils/src/LightPoint.slh | 4 +- libraries/render-utils/src/LightSpot.slh | 2 +- .../src/deferred_light_limited.slv | 24 ++-- .../render-utils/src/deferred_light_spot.slv | 61 +++----- libraries/render-utils/src/spot_light.slf | 2 + 8 files changed, 107 insertions(+), 120 deletions(-) diff --git a/libraries/model/src/model/Light.cpp b/libraries/model/src/model/Light.cpp index 4421864569..c073e397dd 100755 --- a/libraries/model/src/model/Light.cpp +++ b/libraries/model/src/model/Light.cpp @@ -167,7 +167,7 @@ void Light::setAmbientMapNumMips(uint16_t numMips) { void Light::updateVolumeGeometry() { // enlarge the scales slightly to account for tesselation const float SCALE_EXPANSION = 0.05f; - glm::vec4 volumeGeometry(0.0f, 0.0f, 0.0f, 1.0f); // getMaximumRadius() * (1.0f + SCALE_EXPANSION)); + glm::vec4 volumeGeometry(0.0f, 0.0f, 0.0f, getMaximumRadius() * (1.0f + SCALE_EXPANSION)); if (getType() == SPOT) { const float TANGENT_LENGTH_SCALE = 0.666f; diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index af98422b92..e8b50b61ce 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -245,11 +245,50 @@ void DeferredLightingEffect::setGlobalLight(const model::LightPointer& light) { globalLight->setAmbientMap(light->getAmbientMap()); } +#include + +model::MeshPointer DeferredLightingEffect::getPointLightMesh() { + if (!_pointLightMesh) { + _pointLightMesh = std::make_shared(); + + // let's use a icosahedron + auto solid = geometry::icosahedron(); + solid.fitDimension(1.05f); // scaled to 1.05 meters, it will be scaled by the shader accordingly to the light size + + int verticesSize = solid.vertices.size() * 3 * sizeof(float); + float* vertexData = (float*) solid.vertices.data(); + + _pointLightMesh->setVertexBuffer(gpu::BufferView(new gpu::Buffer(verticesSize, (gpu::Byte*) vertexData), gpu::Element::VEC3F_XYZ)); + + auto nbIndices = solid.faces.size() * 3; + + gpu::uint16* indexData = new gpu::uint16[nbIndices]; + gpu::uint16* index = indexData; + for (auto face : solid.faces) { + *(index++) = face[0]; + *(index++) = face[1]; + *(index++) = face[2]; + } + + _pointLightMesh->setIndexBuffer(gpu::BufferView(new gpu::Buffer(sizeof(unsigned short) * nbIndices, (gpu::Byte*) indexData), gpu::Element::INDEX_UINT16)); + delete[] indexData; + + + std::vector parts; + parts.push_back(model::Mesh::Part(0, nbIndices, 0, model::Mesh::TRIANGLES)); + parts.push_back(model::Mesh::Part(0, nbIndices, 0, model::Mesh::LINE_STRIP)); // outline version + + + _pointLightMesh->setPartBuffer(gpu::BufferView(new gpu::Buffer(parts.size() * sizeof(model::Mesh::Part), (gpu::Byte*) parts.data()), gpu::Element::PART_DRAWCALL)); + } + return _pointLightMesh; +} + model::MeshPointer DeferredLightingEffect::getSpotLightMesh() { if (!_spotLightMesh) { _spotLightMesh = std::make_shared(); - int slices = 32; + int slices = 16; int rings = 3; int vertices = 2 + rings * slices; int originVertex = vertices - 2; @@ -544,41 +583,30 @@ void RenderDeferredLocals::run(const render::SceneContextPointer& sceneContext, gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { // THe main viewport is assumed to be the mono viewport (or the 2 stereo faces side by side within that viewport) - auto monoViewport = args->_viewport; + auto viewport = args->_viewport; // The view frustum is the mono frustum base auto viewFrustum = args->getViewFrustum(); // Eval the mono projection - mat4 monoProjMat; - viewFrustum.evalProjectionMatrix(monoProjMat); + mat4 projMat; + viewFrustum.evalProjectionMatrix(projMat); - // The mono view transform - Transform monoViewTransform; - viewFrustum.evalViewTransform(monoViewTransform); + // The view transform + Transform viewTransform; + viewFrustum.evalViewTransform(viewTransform); - // THe mono view matrix coming from the mono view transform - glm::mat4 monoViewMat; - monoViewTransform.getMatrix(monoViewMat); - - auto geometryCache = DependencyManager::get(); - - auto eyePoint = viewFrustum.getPosition(); - float nearRadius = glm::distance(eyePoint, viewFrustum.getNearTopLeft()); auto deferredLightingEffect = DependencyManager::get(); - // Render in this side's viewport - batch.setViewportTransform(monoViewport); - batch.setStateScissorRect(monoViewport); + // Render in this viewport + batch.setViewportTransform(viewport); + batch.setStateScissorRect(viewport); - // enlarge the scales slightly to account for tesselation - const float SCALE_EXPANSION = 0.05f; + auto textureFrameTransform = gpu::Framebuffer::evalSubregionTexcoordTransformCoefficients(deferredFramebuffer->getFrameSize(), viewport); - auto textureFrameTransform = gpu::Framebuffer::evalSubregionTexcoordTransformCoefficients(deferredFramebuffer->getFrameSize(), monoViewport); - - batch.setProjectionTransform(monoProjMat); - batch.setViewTransform(monoViewTransform, true); + batch.setProjectionTransform(projMat); + batch.setViewTransform(viewTransform, true); // Splat Point lights if (points && !deferredLightingEffect->_pointLights.empty()) { @@ -586,32 +614,26 @@ void RenderDeferredLocals::run(const render::SceneContextPointer& sceneContext, batch.setPipeline(deferredLightingEffect->_pointLight); batch._glUniform4fv(deferredLightingEffect->_pointLightLocations->texcoordFrameTransform, 1, reinterpret_cast< const float* >(&textureFrameTransform)); + // Pojnt mesh + auto mesh = deferredLightingEffect->getPointLightMesh(); + batch.setIndexBuffer(mesh->getIndexBuffer()); + batch.setInputBuffer(0, mesh->getVertexBuffer()); + batch.setInputFormat(mesh->getVertexFormat()); + auto& spherePart = mesh->getPartBuffer().get(0); + for (auto lightID : deferredLightingEffect->_pointLights) { auto light = deferredLightingEffect->getLightStage().getLight(lightID); if (!light) { continue; } - // IN DEBUG: light->setShowContour(true); batch.setUniformBuffer(deferredLightingEffect->_pointLightLocations->lightBufferUnit, light->getSchemaBuffer()); - - float expandedRadius = light->getMaximumRadius() * (1.0f + SCALE_EXPANSION); - // glm::vec4 sphereParam(expandedRadius, 0.0f, 0.0f, 1.0f); - - // TODO: We shouldn;t have to do that test and use a different volume geometry for when inside the vlight volume, - // we should be able to draw thre same geometry use DepthClamp but for unknown reason it's s not working... - /* if (glm::distance(eyePoint, glm::vec3(light->getPosition())) < expandedRadius + nearRadius) { - sphereParam.w = 0.0f; - batch._glUniform4fv(deferredLightingEffect->_pointLightLocations->sphereParam, 1, reinterpret_cast< const float* >(&sphereParam)); - batch.draw(gpu::TRIANGLE_STRIP, 4); - } else*/ { - // sphereParam.w = 1.0f; - // batch._glUniform4fv(deferredLightingEffect->_pointLightLocations->sphereParam, 1, reinterpret_cast< const float* >(&sphereParam)); - + { Transform model; model.setTranslation(glm::vec3(light->getPosition().x, light->getPosition().y, light->getPosition().z)); - batch.setModelTransform(model.postScale(expandedRadius)); - batch._glColor4f(1.0f, 1.0f, 1.0f, 1.0f); - geometryCache->renderSphere(batch); + batch.setModelTransform(model); + + batch.drawIndexed(model::Mesh::topologyToPrimitive(spherePart._topology), spherePart._numIndices, spherePart._startIndex); + } } } @@ -634,34 +656,12 @@ void RenderDeferredLocals::run(const render::SceneContextPointer& sceneContext, if (!light) { continue; } - // IN DEBUG: - // light->setShowContour(true); batch.setUniformBuffer(deferredLightingEffect->_spotLightLocations->lightBufferUnit, light->getSchemaBuffer()); - - /* auto eyeLightPos = eyePoint - light->getPosition(); - auto eyeHalfPlaneDistance = glm::dot(eyeLightPos, light->getDirection()); - - const float TANGENT_LENGTH_SCALE = 0.666f; - glm::vec4 coneParam(light->getSpotAngleCosSin(), TANGENT_LENGTH_SCALE * tanf(0.5f * light->getSpotAngle()), 1.0f); - - float expandedRadius = light->getMaximumRadius() * (1.0f + SCALE_EXPANSION); - // TODO: We shouldn;t have to do that test and use a different volume geometry for when inside the vlight volume, - // we should be able to draw thre same geometry use DepthClamp but for unknown reason it's s not working... - const float OVER_CONSERVATIVE_SCALE = 1.1f; - if ((eyeHalfPlaneDistance > -nearRadius) && - (glm::distance(eyePoint, glm::vec3(light->getPosition())) < (expandedRadius * OVER_CONSERVATIVE_SCALE) + nearRadius)) { - coneParam.w = 0.0f; - batch._glUniform4fv(deferredLightingEffect->_spotLightLocations->coneParam, 1, reinterpret_cast< const float* >(&coneParam)); - batch.draw(gpu::TRIANGLE_STRIP, 4); - } else*/ { - // coneParam.w = 1.0f; - // batch._glUniform4fv(deferredLightingEffect->_spotLightLocations->coneParam, 1, reinterpret_cast< const float* >(&coneParam)); + { Transform model; model.setTranslation(light->getPosition()); model.postRotate(light->getOrientation()); - // model.postScale(glm::vec3(expandedRadius, expandedRadius, expandedRadius)); - batch.setModelTransform(model); batch.drawIndexed(model::Mesh::topologyToPrimitive(conePart._topology), conePart._numIndices, conePart._startIndex); diff --git a/libraries/render-utils/src/DeferredLightingEffect.h b/libraries/render-utils/src/DeferredLightingEffect.h index ff0db1330f..9e53bd5cbc 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.h +++ b/libraries/render-utils/src/DeferredLightingEffect.h @@ -73,6 +73,8 @@ private: bool _shadowMapEnabled{ false }; bool _ambientOcclusionEnabled{ false }; + model::MeshPointer _pointLightMesh; + model::MeshPointer getPointLightMesh(); model::MeshPointer _spotLightMesh; model::MeshPointer getSpotLightMesh(); diff --git a/libraries/render-utils/src/LightPoint.slh b/libraries/render-utils/src/LightPoint.slh index 5c9e66dd24..767a96fb51 100644 --- a/libraries/render-utils/src/LightPoint.slh +++ b/libraries/render-utils/src/LightPoint.slh @@ -39,10 +39,10 @@ void evalLightingPoint(out vec3 diffuse, out vec3 specular, Light light, if (isShowLightContour() > 0.0) { // Show edge - float edge = abs(2.0 * ((getLightRadius(light) - fragLightDistance) / (0.1)) - 1.0); + float edge = abs(2.0 * ((getLightCutoffRadius(light) - fragLightDistance) / (0.1)) - 1.0); if (edge < 1) { float edgeCoord = exp2(-8.0*edge*edge); - diffuse = vec3(edgeCoord * edgeCoord * getLightShowContour(light) * getLightColor(light)); + diffuse = vec3(edgeCoord * edgeCoord * getLightColor(light)); } } } diff --git a/libraries/render-utils/src/LightSpot.slh b/libraries/render-utils/src/LightSpot.slh index 8a17a5ef4d..65a417110a 100644 --- a/libraries/render-utils/src/LightSpot.slh +++ b/libraries/render-utils/src/LightSpot.slh @@ -40,7 +40,7 @@ void evalLightingSpot(out vec3 diffuse, out vec3 specular, Light light, if (isShowLightContour() > 0.0) { // Show edges - float edgeDistR = (getLightRadius(light) - fragLightDistance); + float edgeDistR = (getLightCutoffRadius(light) - fragLightDistance); float edgeDistS = dot(fragLightDistance * vec2(cosSpotAngle, sqrt(1.0 - cosSpotAngle * cosSpotAngle)), -getLightSpotOutsideNormal2(light)); float edgeDist = min(edgeDistR, edgeDistS); float edge = abs(2.0 * (edgeDist / (0.1)) - 1.0); diff --git a/libraries/render-utils/src/deferred_light_limited.slv b/libraries/render-utils/src/deferred_light_limited.slv index 7168d5386d..0284e12458 100644 --- a/libraries/render-utils/src/deferred_light_limited.slv +++ b/libraries/render-utils/src/deferred_light_limited.slv @@ -18,27 +18,27 @@ <$declareStandardTransform()$> -!> +<@include model/Light.slh@> out vec4 _texCoord0; void main(void) { vec4 sphereVertex = inPosition; - // vec4 sphereParam = getLightVolumeGeometry(getLight()); + vec4 sphereParam = getLightVolumeGeometry(getLight()); - // sphereVertex.xyz *= sphereParam.w; + sphereVertex.xyz *= sphereParam.w; // standard transform - TransformCamera cam = getTransformCamera(); - TransformObject obj = getTransformObject(); - <$transformModelToClipPos(cam, obj, sphereVertex, gl_Position)$>; + TransformCamera cam = getTransformCamera(); + TransformObject obj = getTransformObject(); + <$transformModelToClipPos(cam, obj, sphereVertex, gl_Position)$>; - vec4 projected = gl_Position / gl_Position.w; - projected.xy = (projected.xy + 1.0) * 0.5; + vec4 projected = gl_Position / gl_Position.w; + projected.xy = (projected.xy + 1.0) * 0.5; - if (cam_isStereo()) { - projected.x = 0.5 * (projected.x + cam_getStereoSide()); - } - _texCoord0 = vec4(projected.xy, 0.0, 1.0) * gl_Position.w; + if (cam_isStereo()) { + projected.x = 0.5 * (projected.x + cam_getStereoSide()); + } + _texCoord0 = vec4(projected.xy, 0.0, 1.0) * gl_Position.w; } diff --git a/libraries/render-utils/src/deferred_light_spot.slv b/libraries/render-utils/src/deferred_light_spot.slv index e48f8ba907..ef019f5a16 100755 --- a/libraries/render-utils/src/deferred_light_spot.slv +++ b/libraries/render-utils/src/deferred_light_spot.slv @@ -20,53 +20,36 @@ <@include model/Light.slh@> - out vec4 _texCoord0; void main(void) { vec4 coneVertex = inPosition; - // if (coneParam.w != 0.0) { vec4 coneParam = getLightVolumeGeometry(getLight()); - if(coneVertex.z >= 0.0) { - // Evaluate the true position of the spot volume - vec2 dir = float(coneVertex.z < 0.5f) * (coneParam.xy - + vec2(coneParam.y, -coneParam.x) * coneParam.z * float(coneVertex.z > 0.0f)) - + float(coneVertex.z > 0.5f) * (vec2(1.0, 0.0) - + vec2(0.0, coneParam.z) * float(coneVertex.z < 1.0f)); - coneVertex.xy *= dir.y; - coneVertex.z = -dir.x; - } else { - coneVertex.z = 0.0; - } + if(coneVertex.z >= 0.0) { + // Evaluate the true position of the spot volume + vec2 dir = float(coneVertex.z < 0.5f) * (coneParam.xy + + vec2(coneParam.y, -coneParam.x) * coneParam.z * float(coneVertex.z > 0.0f)) + + float(coneVertex.z > 0.5f) * (vec2(1.0, 0.0) + + vec2(0.0, coneParam.z) * float(coneVertex.z < 1.0f)); - coneVertex.xyz *= coneParam.w; + coneVertex.xy *= dir.y; + coneVertex.z = -dir.x; + } else { + coneVertex.z = 0.0; + } - // standard transform - TransformCamera cam = getTransformCamera(); - TransformObject obj = getTransformObject(); - <$transformModelToClipPos(cam, obj, coneVertex, gl_Position)$>; - vec4 projected = gl_Position / gl_Position.w; - projected.xy = (projected.xy + 1.0) * 0.5; + coneVertex.xyz *= coneParam.w; - if (cam_isStereo()) { - projected.x = 0.5 * (projected.x + cam_getStereoSide()); - } - _texCoord0 = vec4(projected.xy, 0.0, 1.0) * gl_Position.w; - /* } else { - const float depth = -1.0; //Draw at near plane - const vec4 UNIT_QUAD[4] = vec4[4]( - vec4(-1.0, -1.0, depth, 1.0), - vec4(1.0, -1.0, depth, 1.0), - vec4(-1.0, 1.0, depth, 1.0), - vec4(1.0, 1.0, depth, 1.0) - ); - vec4 pos = UNIT_QUAD[gl_VertexID]; + // standard transform + TransformCamera cam = getTransformCamera(); + TransformObject obj = getTransformObject(); + <$transformModelToClipPos(cam, obj, coneVertex, gl_Position)$>; + vec4 projected = gl_Position / gl_Position.w; + projected.xy = (projected.xy + 1.0) * 0.5; - _texCoord0 = vec4((pos.xy + 1) * 0.5, 0.0, 1.0); - if (cam_isStereo()) { - _texCoord0.x = 0.5 * (_texCoord0.x + cam_getStereoSide()); - } - gl_Position = pos; - }*/ + if (cam_isStereo()) { + projected.x = 0.5 * (projected.x + cam_getStereoSide()); + } + _texCoord0 = vec4(projected.xy, 0.0, 1.0) * gl_Position.w; } diff --git a/libraries/render-utils/src/spot_light.slf b/libraries/render-utils/src/spot_light.slf index c2d99259db..1c249e716f 100644 --- a/libraries/render-utils/src/spot_light.slf +++ b/libraries/render-utils/src/spot_light.slf @@ -77,5 +77,7 @@ void main(void) { _fragColor.rgb += diffuse; _fragColor.rgb += specular; + + // _fragColor.rgb = vec3(0.0, 1.0, 1.0); } From 560163bb754d0ec0d9b23ece0af1c761ddae9d66 Mon Sep 17 00:00:00 2001 From: samcake Date: Fri, 2 Sep 2016 10:51:19 -0700 Subject: [PATCH 09/75] removing a warning --- tests/render-perf/src/main.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/render-perf/src/main.cpp b/tests/render-perf/src/main.cpp index 030a39a1cd..d1eaba5f25 100644 --- a/tests/render-perf/src/main.cpp +++ b/tests/render-perf/src/main.cpp @@ -526,7 +526,6 @@ public: _octree->init(); // Prevent web entities from rendering REGISTER_ENTITY_TYPE_WITH_FACTORY(Web, WebEntityItem::factory); -// REGISTER_ENTITY_TYPE_WITH_FACTORY(Light, LightEntityItem::factory); DependencyManager::set(_octree->getTree()); getEntities()->setViewFrustum(_viewFrustum); From d2a15ca82cfb249c5406974bbc7cc8dd310de07c Mon Sep 17 00:00:00 2001 From: samcake Date: Fri, 2 Sep 2016 17:51:35 -0700 Subject: [PATCH 10/75] Trying to migrate to a light array instead of each individual lights --- libraries/gpu/src/gpu/Transform.slh | 8 ++++ libraries/model/src/model/Light.slh | 14 ++++++ .../render-utils/src/DeferredBufferRead.slh | 48 +++++++++++++++++++ .../render-utils/src/DeferredGlobalLight.slh | 1 + .../src/DeferredLightingEffect.cpp | 29 ++++++++--- .../render-utils/src/DeferredLightingEffect.h | 7 ++- libraries/render-utils/src/LightStage.cpp | 21 ++++++++ libraries/render-utils/src/LightStage.h | 3 ++ .../src/deferred_light_limited.slv | 1 + .../render-utils/src/deferred_light_spot.slv | 20 ++++++-- libraries/render-utils/src/overlay3D.slf | 1 + .../src/overlay3D_translucent.slf | 1 + libraries/render-utils/src/point_light.slf | 1 + libraries/render-utils/src/spot_light.slf | 25 +++++++--- .../subsurfaceScattering_drawScattering.slf | 1 + 15 files changed, 161 insertions(+), 20 deletions(-) diff --git a/libraries/gpu/src/gpu/Transform.slh b/libraries/gpu/src/gpu/Transform.slh index 12a1cd10f1..0f13a6b4d1 100644 --- a/libraries/gpu/src/gpu/Transform.slh +++ b/libraries/gpu/src/gpu/Transform.slh @@ -128,6 +128,14 @@ TransformObject getTransformObject() { } <@endfunc@> + +<@func transformWorldToClipPos(cameraTransform, worldPos, clipPos)@> + { // transformWorldToClipPos + vec4 eyeWAPos = <$worldPos$> - vec4(<$cameraTransform$>._viewInverse[3].xyz, 0.0); + <$clipPos$> = <$cameraTransform$>._projectionViewUntranslated * eyeWAPos; + } +<@endfunc@> + <@func transformModelToWorldPos(objectTransform, modelPos, worldPos)@> { // transformModelToWorldPos <$worldPos$> = (<$objectTransform$>._model * <$modelPos$>); diff --git a/libraries/model/src/model/Light.slh b/libraries/model/src/model/Light.slh index de2ca97088..59e986e14a 100644 --- a/libraries/model/src/model/Light.slh +++ b/libraries/model/src/model/Light.slh @@ -131,7 +131,17 @@ float getLightAmbientMapNumMips(Light l) { return l._control.x; } +<@func declareLightBuffer(N)@> +<@if N@> +uniform lightBuffer { + Light lightArray[<$N$>]; +}; + +Light getLight(int index) { + return lightArray[index]; +} +<@else@> uniform lightBuffer { Light light; }; @@ -139,6 +149,10 @@ Light getLight() { return light; } +<@endif@> + +<@endfunc@> + diff --git a/libraries/render-utils/src/DeferredBufferRead.slh b/libraries/render-utils/src/DeferredBufferRead.slh index 6b5060cc5f..d7eee23c1f 100644 --- a/libraries/render-utils/src/DeferredBufferRead.slh +++ b/libraries/render-utils/src/DeferredBufferRead.slh @@ -24,6 +24,7 @@ uniform sampler2D specularMap; // the depth texture uniform sampler2D depthMap; +uniform sampler2D linearZeyeMap; // the obscurance texture uniform sampler2D obscuranceMap; @@ -86,6 +87,40 @@ DeferredFragment unpackDeferredFragmentNoPosition(vec2 texcoord) { } +DeferredFragment unpackDeferredFragmentNoPositionNoAmbient(vec2 texcoord) { + vec4 normalVal; + vec4 diffuseVal; + + DeferredFragment frag; + frag.depthVal = -1; + normalVal = texture(normalMap, texcoord); + diffuseVal = texture(albedoMap, texcoord); + + // Unpack the normal from the map + frag.normal = unpackNormal(normalVal.xyz); + frag.roughness = normalVal.a; + + // Diffuse color and unpack the mode and the metallicness + frag.albedo = diffuseVal.xyz; + frag.scattering = 0.0; + unpackModeMetallic(diffuseVal.w, frag.mode, frag.metallic); + + //frag.emissive = specularVal.xyz; + frag.obscurance = 1.0; + + + if (frag.metallic <= 0.5) { + frag.metallic = 0.0; + frag.fresnel = vec3(0.03); // Default Di-electric fresnel value + } else { + frag.fresnel = vec3(diffuseVal.xyz); + frag.metallic = 1.0; + } + + return frag; +} + + <@include DeferredTransform.slh@> <$declareDeferredFrameTransform()$> @@ -103,6 +138,19 @@ vec4 unpackDeferredPosition(DeferredFrameTransform deferredTransform, float dept return vec4(evalEyePositionFromZeye(side, Zeye, texcoord), 1.0); } +vec4 unpackDeferredPositionFromZeye(vec2 texcoord) { + float Zeye = -texture(linearZeyeMap, texcoord).x; + int side = 0; + if (isStereo()) { + if (texcoord.x > 0.5) { + texcoord.x -= 0.5; + side = 1; + } + texcoord.x *= 2.0; + } + return vec4(evalEyePositionFromZeye(side, Zeye, texcoord), 1.0); +} + DeferredFragment unpackDeferredFragment(DeferredFrameTransform deferredTransform, vec2 texcoord) { float depthValue = texture(depthMap, texcoord).r; diff --git a/libraries/render-utils/src/DeferredGlobalLight.slh b/libraries/render-utils/src/DeferredGlobalLight.slh index 16cdab535c..cb5dd9dc48 100755 --- a/libraries/render-utils/src/DeferredGlobalLight.slh +++ b/libraries/render-utils/src/DeferredGlobalLight.slh @@ -14,6 +14,7 @@ <@include model/Light.slh@> <@include LightingModel.slh@> +<$declareLightBuffer()$> <@include LightAmbient.slh@> <@include LightDirectional.slh@> diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index e8b50b61ce..30b7f83072 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -44,9 +44,8 @@ struct LightLocations { int radius{ -1 }; int ambientSphere{ -1 }; int lightBufferUnit{ -1 }; + int lightIndexBufferUnit { -1 }; int texcoordFrameTransform{ -1 }; - int sphereParam{ -1 }; - int coneParam{ -1 }; int deferredFrameTransformBuffer{ -1 }; int subsurfaceScatteringParametersBuffer{ -1 }; int shadowTransformBuffer{ -1 }; @@ -60,6 +59,7 @@ enum DeferredShader_MapSlot { DEFERRED_BUFFER_OBSCURANCE_UNIT = 4, SHADOW_MAP_UNIT = 5, SKYBOX_MAP_UNIT = 6, + DEFERRED_BUFFER_LINEAR_DEPTH_UNIT, DEFERRED_BUFFER_CURVATURE_UNIT, DEFERRED_BUFFER_DIFFUSED_CURVATURE_UNIT, SCATTERING_LUT_UNIT, @@ -71,6 +71,7 @@ enum DeferredShader_BufferSlot { SCATTERING_PARAMETERS_BUFFER_SLOT, LIGHTING_MODEL_BUFFER_SLOT = render::ShapePipeline::Slot::LIGHTING_MODEL, LIGHT_GPU_SLOT = render::ShapePipeline::Slot::LIGHT, + LIGHT_INDEX_GPU_SLOT, }; static void loadLightProgram(const char* vertSource, const char* fragSource, bool lightVolume, gpu::PipelinePointer& program, LightLocationsPtr& locations); @@ -184,6 +185,7 @@ static void loadLightProgram(const char* vertSource, const char* fragSource, boo slotBindings.insert(gpu::Shader::Binding(std::string("shadowMap"), SHADOW_MAP_UNIT)); slotBindings.insert(gpu::Shader::Binding(std::string("skyboxMap"), SKYBOX_MAP_UNIT)); + slotBindings.insert(gpu::Shader::Binding(std::string("linearZeyeMap"), DEFERRED_BUFFER_LINEAR_DEPTH_UNIT)); slotBindings.insert(gpu::Shader::Binding(std::string("curvatureMap"), DEFERRED_BUFFER_CURVATURE_UNIT)); slotBindings.insert(gpu::Shader::Binding(std::string("diffusedCurvatureMap"), DEFERRED_BUFFER_DIFFUSED_CURVATURE_UNIT)); slotBindings.insert(gpu::Shader::Binding(std::string("scatteringLUT"), SCATTERING_LUT_UNIT)); @@ -195,6 +197,7 @@ static void loadLightProgram(const char* vertSource, const char* fragSource, boo slotBindings.insert(gpu::Shader::Binding(std::string("lightingModelBuffer"), LIGHTING_MODEL_BUFFER_SLOT)); slotBindings.insert(gpu::Shader::Binding(std::string("subsurfaceScatteringParametersBuffer"), SCATTERING_PARAMETERS_BUFFER_SLOT)); slotBindings.insert(gpu::Shader::Binding(std::string("lightBuffer"), LIGHT_GPU_SLOT)); + slotBindings.insert(gpu::Shader::Binding(std::string("lightIndexBuffer"), LIGHT_INDEX_GPU_SLOT)); gpu::Shader::makeProgram(*program, slotBindings); @@ -203,10 +206,9 @@ static void loadLightProgram(const char* vertSource, const char* fragSource, boo locations->ambientSphere = program->getUniforms().findLocation("ambientSphere.L00"); locations->texcoordFrameTransform = program->getUniforms().findLocation("texcoordFrameTransform"); - locations->sphereParam = program->getUniforms().findLocation("sphereParam"); - locations->coneParam = program->getUniforms().findLocation("coneParam"); locations->lightBufferUnit = program->getBuffers().findLocation("lightBuffer"); + locations->lightIndexBufferUnit = program->getBuffers().findLocation("lightIndexBuffer"); locations->deferredFrameTransformBuffer = program->getBuffers().findLocation("deferredFrameTransformBuffer"); locations->subsurfaceScatteringParametersBuffer = program->getBuffers().findLocation("subsurfaceScatteringParametersBuffer"); locations->shadowTransformBuffer = program->getBuffers().findLocation("shadowTransformBuffer"); @@ -496,6 +498,7 @@ void RenderDeferredSetup::run(const render::SceneContextPointer& sceneContext, c // Subsurface scattering specific if (surfaceGeometryFramebuffer) { + batch.setResourceTexture(DEFERRED_BUFFER_LINEAR_DEPTH_UNIT, surfaceGeometryFramebuffer->getLinearDepthTexture()); batch.setResourceTexture(DEFERRED_BUFFER_CURVATURE_UNIT, surfaceGeometryFramebuffer->getCurvatureTexture()); batch.setResourceTexture(DEFERRED_BUFFER_DIFFUSED_CURVATURE_UNIT, surfaceGeometryFramebuffer->getLowCurvatureTexture()); } @@ -571,7 +574,8 @@ void RenderDeferredSetup::run(const render::SceneContextPointer& sceneContext, c void RenderDeferredLocals::run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext, const DeferredFrameTransformPointer& frameTransform, const DeferredFramebufferPointer& deferredFramebuffer, - const LightingModelPointer& lightingModel) { + const LightingModelPointer& lightingModel, + const SurfaceGeometryFramebufferPointer& surfaceGeometryFramebuffer) { bool points = lightingModel->isPointLightEnabled(); bool spots = lightingModel->isSpotLightEnabled(); @@ -638,8 +642,13 @@ void RenderDeferredLocals::run(const render::SceneContextPointer& sceneContext, } } + // Splat spot lights if (spots && !deferredLightingEffect->_spotLights.empty()) { + + + _spotLightsBuffer._buffer->setData(deferredLightingEffect->_spotLights.size() * sizeof(int), (const gpu::Byte*) deferredLightingEffect->_spotLights.data()); + // Spot light pipeline batch.setPipeline(deferredLightingEffect->_spotLight); batch._glUniform4fv(deferredLightingEffect->_spotLightLocations->texcoordFrameTransform, 1, reinterpret_cast< const float* >(&textureFrameTransform)); @@ -651,6 +660,11 @@ void RenderDeferredLocals::run(const render::SceneContextPointer& sceneContext, batch.setInputFormat(mesh->getVertexFormat()); auto& conePart = mesh->getPartBuffer().get(0); + + batch.setUniformBuffer(deferredLightingEffect->_spotLightLocations->lightBufferUnit, deferredLightingEffect->getLightStage()._lightArrayBuffer); + batch.setUniformBuffer(deferredLightingEffect->_spotLightLocations->lightIndexBufferUnit, _spotLightsBuffer); + batch.drawIndexedInstanced(deferredLightingEffect->_spotLights.size(), model::Mesh::topologyToPrimitive(conePart._topology), conePart._numIndices, conePart._startIndex); + /* for (auto lightID : deferredLightingEffect->_spotLights) { auto light = deferredLightingEffect->getLightStage().getLight(lightID); if (!light) { @@ -666,7 +680,7 @@ void RenderDeferredLocals::run(const render::SceneContextPointer& sceneContext, batch.drawIndexed(model::Mesh::topologyToPrimitive(conePart._topology), conePart._numIndices, conePart._startIndex); } - } + }*/ } }); } @@ -681,6 +695,7 @@ void RenderDeferredCleanup::run(const render::SceneContextPointer& sceneContext, batch.setResourceTexture(DEFERRED_BUFFER_DEPTH_UNIT, nullptr); batch.setResourceTexture(DEFERRED_BUFFER_OBSCURANCE_UNIT, nullptr); + batch.setResourceTexture(DEFERRED_BUFFER_LINEAR_DEPTH_UNIT, nullptr); batch.setResourceTexture(DEFERRED_BUFFER_CURVATURE_UNIT, nullptr); batch.setResourceTexture(DEFERRED_BUFFER_DIFFUSED_CURVATURE_UNIT, nullptr); batch.setResourceTexture(SCATTERING_LUT_UNIT, nullptr); @@ -731,7 +746,7 @@ void RenderDeferred::run(const SceneContextPointer& sceneContext, const RenderCo setupJob.run(sceneContext, renderContext, deferredTransform, deferredFramebuffer, lightingModel, surfaceGeometryFramebuffer, ssaoFramebuffer, subsurfaceScatteringResource); - lightsJob.run(sceneContext, renderContext, deferredTransform, deferredFramebuffer, lightingModel); + lightsJob.run(sceneContext, renderContext, deferredTransform, deferredFramebuffer, lightingModel, surfaceGeometryFramebuffer); cleanupJob.run(sceneContext, renderContext); diff --git a/libraries/render-utils/src/DeferredLightingEffect.h b/libraries/render-utils/src/DeferredLightingEffect.h index 9e53bd5cbc..018ff698eb 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.h +++ b/libraries/render-utils/src/DeferredLightingEffect.h @@ -106,6 +106,7 @@ private: std::vector _globalLights; std::vector _pointLights; std::vector _spotLights; + friend class RenderDeferredSetup; friend class RenderDeferredLocals; @@ -155,7 +156,11 @@ public: void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext, const DeferredFrameTransformPointer& frameTransform, const DeferredFramebufferPointer& deferredFramebuffer, - const LightingModelPointer& lightingModel); + const LightingModelPointer& lightingModel, + const SurfaceGeometryFramebufferPointer& surfaceGeometryFramebuffer); + + gpu::BufferView _spotLightsBuffer; + }; diff --git a/libraries/render-utils/src/LightStage.cpp b/libraries/render-utils/src/LightStage.cpp index 5db1f99532..8909284a02 100644 --- a/libraries/render-utils/src/LightStage.cpp +++ b/libraries/render-utils/src/LightStage.cpp @@ -114,9 +114,30 @@ LightStage::Index LightStage::addLight(const LightPointer& light) { // INsert the light and its index in the reverese map _lightMap.insert(LightMap::value_type(light, lightId)); + + updateLightArrayBuffer(lightId); } return lightId; } else { return (*found).second; } } + +void LightStage::updateLightArrayBuffer(Index lightId) { + if (!_lightArrayBuffer) { + _lightArrayBuffer = std::make_shared(); + } + + assert(checkLightId(lightId)); + auto lightSize = sizeof(model::Light::Schema); + + if (lightId > _lightArrayBuffer->getTypedSize()) { + _lightArrayBuffer->resize(lightSize * (lightId + 10)); + } + + // lightArray is big enough so we can remap + auto& light = _lights._elements[lightId]; + auto lightSchema = light->getSchemaBuffer().get(); + _lightArrayBuffer->setSubData(lightId, lightSchema); +} + diff --git a/libraries/render-utils/src/LightStage.h b/libraries/render-utils/src/LightStage.h index a050bb393f..dc80375f36 100644 --- a/libraries/render-utils/src/LightStage.h +++ b/libraries/render-utils/src/LightStage.h @@ -240,6 +240,9 @@ public: LightMap _lightMap; Descs _descs; + gpu::BufferPointer _lightArrayBuffer; + void updateLightArrayBuffer(Index lightId); + Shadows _shadows; }; diff --git a/libraries/render-utils/src/deferred_light_limited.slv b/libraries/render-utils/src/deferred_light_limited.slv index 0284e12458..4598447335 100644 --- a/libraries/render-utils/src/deferred_light_limited.slv +++ b/libraries/render-utils/src/deferred_light_limited.slv @@ -19,6 +19,7 @@ <$declareStandardTransform()$> <@include model/Light.slh@> +<$declareLightBuffer()$> out vec4 _texCoord0; diff --git a/libraries/render-utils/src/deferred_light_spot.slv b/libraries/render-utils/src/deferred_light_spot.slv index ef019f5a16..b05e9719f4 100755 --- a/libraries/render-utils/src/deferred_light_spot.slv +++ b/libraries/render-utils/src/deferred_light_spot.slv @@ -19,12 +19,16 @@ <$declareStandardTransform()$> <@include model/Light.slh@> +<$declareLightBuffer(32)$> out vec4 _texCoord0; void main(void) { vec4 coneVertex = inPosition; - vec4 coneParam = getLightVolumeGeometry(getLight()); + + Light light = getLight(gl_InstanceID); + vec3 lightPos = getLightPosition(light); + vec4 coneParam = getLightVolumeGeometry(light); if(coneVertex.z >= 0.0) { // Evaluate the true position of the spot volume @@ -37,15 +41,21 @@ void main(void) { coneVertex.z = -dir.x; } else { coneVertex.z = 0.0; - } + } coneVertex.xyz *= coneParam.w; + coneVertex.xyz += lightPos; + // standard transform TransformCamera cam = getTransformCamera(); - TransformObject obj = getTransformObject(); - <$transformModelToClipPos(cam, obj, coneVertex, gl_Position)$>; - vec4 projected = gl_Position / gl_Position.w; + + ; !> + + <$transformWorldToClipPos(cam, coneVertex, gl_Position)$>; + + vec4 projected = gl_Position / gl_Position.w; projected.xy = (projected.xy + 1.0) * 0.5; if (cam_isStereo()) { diff --git a/libraries/render-utils/src/overlay3D.slf b/libraries/render-utils/src/overlay3D.slf index b29b9baf64..1a629dedf1 100644 --- a/libraries/render-utils/src/overlay3D.slf +++ b/libraries/render-utils/src/overlay3D.slf @@ -13,6 +13,7 @@ <@include model/Light.slh@> +<$declareLightBuffer()$> <@include LightingModel.slh@> diff --git a/libraries/render-utils/src/overlay3D_translucent.slf b/libraries/render-utils/src/overlay3D_translucent.slf index ce5bbf3589..f45aa897f9 100644 --- a/libraries/render-utils/src/overlay3D_translucent.slf +++ b/libraries/render-utils/src/overlay3D_translucent.slf @@ -13,6 +13,7 @@ // <@include model/Light.slh@> +<$declareLightBuffer()$> <@include LightingModel.slh@> diff --git a/libraries/render-utils/src/point_light.slf b/libraries/render-utils/src/point_light.slf index 6aab2489be..018d6ca79b 100644 --- a/libraries/render-utils/src/point_light.slf +++ b/libraries/render-utils/src/point_light.slf @@ -19,6 +19,7 @@ // Everything about light <@include model/Light.slh@> +<$declareLightBuffer()$> <@include LightingModel.slh@> diff --git a/libraries/render-utils/src/spot_light.slf b/libraries/render-utils/src/spot_light.slf index 1c249e716f..08d8589706 100644 --- a/libraries/render-utils/src/spot_light.slf +++ b/libraries/render-utils/src/spot_light.slf @@ -19,6 +19,7 @@ // Everything about light <@include model/Light.slh@> +<$declareLightBuffer(32)$> <@include LightingModel.slh@> @@ -27,28 +28,27 @@ uniform vec4 texcoordFrameTransform; + + in vec4 _texCoord0; out vec4 _fragColor; void main(void) { - DeferredFrameTransform deferredTransform = getDeferredFrameTransform(); +// DeferredFrameTransform deferredTransform = getDeferredFrameTransform(); // Grab the fragment data from the uv vec2 texCoord = _texCoord0.st / _texCoord0.q; texCoord *= texcoordFrameTransform.zw; texCoord += texcoordFrameTransform.xy; - DeferredFragment frag = unpackDeferredFragment(deferredTransform, texCoord); - if (frag.mode == FRAG_MODE_UNLIT) { - discard; - } + vec4 fragPosition = unpackDeferredPositionFromZeye(texCoord); // Need the light now - Light light = getLight(); + Light light = getLight(0); // Frag pos in world mat4 invViewMat = getViewInverse(); - vec4 fragPos = invViewMat * frag.position; + vec4 fragPos = invViewMat * fragPosition; // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space vec4 fragLightVecLen2; @@ -58,6 +58,17 @@ void main(void) { discard; } + // _fragColor.rgb = vec3(0.0, 1.0, 1.0); + // return; + + DeferredFragment frag = unpackDeferredFragmentNoPositionNoAmbient(texCoord); + // frag.depthVal = depthValue; + frag.position = fragPosition; + + if (frag.mode == FRAG_MODE_UNLIT) { + discard; + } + // Frag to eye vec vec4 fragEyeVector = invViewMat * vec4(-frag.position.xyz, 0.0); vec3 fragEyeDir = normalize(fragEyeVector.xyz); diff --git a/libraries/render-utils/src/subsurfaceScattering_drawScattering.slf b/libraries/render-utils/src/subsurfaceScattering_drawScattering.slf index 7ee65e27e3..981993615c 100644 --- a/libraries/render-utils/src/subsurfaceScattering_drawScattering.slf +++ b/libraries/render-utils/src/subsurfaceScattering_drawScattering.slf @@ -13,6 +13,7 @@ <@include DeferredBufferRead.slh@> <@include model/Light.slh@> +<$declareLightBuffer()$> <$declareDeferredCurvature()$> From b81dfefbebea104da9a02b0461301f0e4853f00a Mon Sep 17 00:00:00 2001 From: sam Date: Sat, 3 Sep 2016 12:08:53 -0700 Subject: [PATCH 11/75] pack all the lights in a single buffer and shade the opaque with a single full screen path --- libraries/model/src/model/Light.slh | 5 + .../src/DeferredLightingEffect.cpp | 62 +++++++++++-- .../render-utils/src/DeferredLightingEffect.h | 2 + .../render-utils/src/deferred_light_spot.slv | 8 +- libraries/render-utils/src/spot_light.slf | 92 +++++++++++-------- 5 files changed, 123 insertions(+), 46 deletions(-) diff --git a/libraries/model/src/model/Light.slh b/libraries/model/src/model/Light.slh index 59e986e14a..2b6e55cf7e 100644 --- a/libraries/model/src/model/Light.slh +++ b/libraries/model/src/model/Light.slh @@ -60,6 +60,11 @@ struct Light { SphericalHarmonics _ambientSphere; }; +const int LIGHT_SPOT = 2; + +bool light_isSpot(Light l) { + return bool(l._control.y >= 2.f); +} vec3 getLightPosition(Light l) { return l._position.xyz; } vec3 getLightDirection(Light l) { return l._direction.xyz; } // direction is -Z axis diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index 30b7f83072..b7e34095c1 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -97,7 +97,7 @@ void DeferredLightingEffect::init() { loadLightProgram(deferred_light_vert, directional_skybox_light_shadow_frag, false, _directionalSkyboxLightShadow, _directionalSkyboxLightShadowLocations); loadLightProgram(deferred_light_limited_vert, point_light_frag, true, _pointLight, _pointLightLocations); - loadLightProgram(deferred_light_spot_vert, spot_light_frag, true, _spotLight, _spotLightLocations); + loadLightProgram(deferred_light_vert, spot_light_frag, false, _spotLight, _spotLightLocations); // Allocate a global light representing the Global Directional light casting shadow (the sun) and the ambient light _allocatedLights.push_back(std::make_shared()); @@ -571,6 +571,11 @@ void RenderDeferredSetup::run(const render::SceneContextPointer& sceneContext, c } +RenderDeferredLocals::RenderDeferredLocals() : +_spotLightsBuffer(std::make_shared()) { + +} + void RenderDeferredLocals::run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext, const DeferredFrameTransformPointer& frameTransform, const DeferredFramebufferPointer& deferredFramebuffer, @@ -585,6 +590,8 @@ void RenderDeferredLocals::run(const render::SceneContextPointer& sceneContext, } auto args = renderContext->args; gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { + // Framebuffer copy operations cannot function as multipass stereo operations. + batch.enableStereo(false); // THe main viewport is assumed to be the mono viewport (or the 2 stereo faces side by side within that viewport) auto viewport = args->_viewport; @@ -609,9 +616,46 @@ void RenderDeferredLocals::run(const render::SceneContextPointer& sceneContext, auto textureFrameTransform = gpu::Framebuffer::evalSubregionTexcoordTransformCoefficients(deferredFramebuffer->getFrameSize(), viewport); - batch.setProjectionTransform(projMat); - batch.setViewTransform(viewTransform, true); + // batch.setProjectionTransform(projMat); + // batch.setViewTransform(viewTransform, true); + // gather lights + auto& srcPointLights = deferredLightingEffect->_pointLights; + auto& srcSpotLights = deferredLightingEffect->_spotLights; + std::vector lightIndices(srcPointLights.size() + srcSpotLights.size() + 1); + lightIndices[0] = 0; + + if (points && !srcPointLights.empty()) { + memcpy(lightIndices.data() + (lightIndices[0] + 1), srcPointLights.data(), srcPointLights.size() * sizeof(int)); + lightIndices[0] += srcPointLights.size(); + } + if (spots && !srcSpotLights.empty()) { + memcpy(lightIndices.data() + (lightIndices[0] + 1), srcSpotLights.data(), srcSpotLights.size() * sizeof(int)); + lightIndices[0] += srcSpotLights.size(); + } + + if (lightIndices[0] > 0) { + _spotLightsBuffer._buffer->setData(lightIndices.size() * sizeof(int), (const gpu::Byte*) lightIndices.data()); + _spotLightsBuffer._size = lightIndices.size() * sizeof(int); + + // Spot light pipeline + batch.setPipeline(deferredLightingEffect->_spotLight); + batch._glUniform4fv(deferredLightingEffect->_spotLightLocations->texcoordFrameTransform, 1, reinterpret_cast< const float* >(&textureFrameTransform)); + + // Spot mesh + auto mesh = deferredLightingEffect->getSpotLightMesh(); + batch.setIndexBuffer(mesh->getIndexBuffer()); + batch.setInputBuffer(0, mesh->getVertexBuffer()); + batch.setInputFormat(mesh->getVertexFormat()); + auto& conePart = mesh->getPartBuffer().get(0); + + + batch.setUniformBuffer(deferredLightingEffect->_spotLightLocations->lightBufferUnit, deferredLightingEffect->getLightStage()._lightArrayBuffer); + batch.setUniformBuffer(deferredLightingEffect->_spotLightLocations->lightIndexBufferUnit, _spotLightsBuffer); + // batch.drawIndexedInstanced(deferredLightingEffect->_spotLights.size(), model::Mesh::topologyToPrimitive(conePart._topology), conePart._numIndices, conePart._startIndex); + + batch.draw(gpu::TRIANGLE_STRIP, 4); + /* // Splat Point lights if (points && !deferredLightingEffect->_pointLights.empty()) { // POint light pipeline @@ -645,9 +689,11 @@ void RenderDeferredLocals::run(const render::SceneContextPointer& sceneContext, // Splat spot lights if (spots && !deferredLightingEffect->_spotLights.empty()) { - - - _spotLightsBuffer._buffer->setData(deferredLightingEffect->_spotLights.size() * sizeof(int), (const gpu::Byte*) deferredLightingEffect->_spotLights.data()); + std::vector again(deferredLightingEffect->_spotLights.size() + 1); + again[0] = deferredLightingEffect->_spotLights.size(); + memcpy(again.data() + 1, deferredLightingEffect->_spotLights.data(), deferredLightingEffect->_spotLights.size() * sizeof(int)); + _spotLightsBuffer._buffer->setData(again.size() * sizeof(int), (const gpu::Byte*) again.data()); + _spotLightsBuffer._size = again.size() * sizeof(int); // Spot light pipeline batch.setPipeline(deferredLightingEffect->_spotLight); @@ -663,7 +709,9 @@ void RenderDeferredLocals::run(const render::SceneContextPointer& sceneContext, batch.setUniformBuffer(deferredLightingEffect->_spotLightLocations->lightBufferUnit, deferredLightingEffect->getLightStage()._lightArrayBuffer); batch.setUniformBuffer(deferredLightingEffect->_spotLightLocations->lightIndexBufferUnit, _spotLightsBuffer); - batch.drawIndexedInstanced(deferredLightingEffect->_spotLights.size(), model::Mesh::topologyToPrimitive(conePart._topology), conePart._numIndices, conePart._startIndex); + // batch.drawIndexedInstanced(deferredLightingEffect->_spotLights.size(), model::Mesh::topologyToPrimitive(conePart._topology), conePart._numIndices, conePart._startIndex); + + batch.draw(gpu::TRIANGLE_STRIP, 4); /* for (auto lightID : deferredLightingEffect->_spotLights) { auto light = deferredLightingEffect->getLightStage().getLight(lightID); diff --git a/libraries/render-utils/src/DeferredLightingEffect.h b/libraries/render-utils/src/DeferredLightingEffect.h index 018ff698eb..1d0eb1cb15 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.h +++ b/libraries/render-utils/src/DeferredLightingEffect.h @@ -161,6 +161,8 @@ public: gpu::BufferView _spotLightsBuffer; + RenderDeferredLocals(); + }; diff --git a/libraries/render-utils/src/deferred_light_spot.slv b/libraries/render-utils/src/deferred_light_spot.slv index b05e9719f4..e99142d8ea 100755 --- a/libraries/render-utils/src/deferred_light_spot.slv +++ b/libraries/render-utils/src/deferred_light_spot.slv @@ -21,12 +21,16 @@ <@include model/Light.slh@> <$declareLightBuffer(32)$> +uniform lightIndexBuffer { + int lightIndex[32]; +}; out vec4 _texCoord0; +flat out int instanceID; void main(void) { vec4 coneVertex = inPosition; - - Light light = getLight(gl_InstanceID); + instanceID = lightIndex[gl_InstanceID]; + Light light = getLight(instanceID); vec3 lightPos = getLightPosition(light); vec4 coneParam = getLightVolumeGeometry(light); diff --git a/libraries/render-utils/src/spot_light.slf b/libraries/render-utils/src/spot_light.slf index 08d8589706..7e1ed9d01e 100644 --- a/libraries/render-utils/src/spot_light.slf +++ b/libraries/render-utils/src/spot_light.slf @@ -20,75 +20,93 @@ // Everything about light <@include model/Light.slh@> <$declareLightBuffer(32)$> - +uniform lightIndexBuffer { + int lightIndex[32]; +}; <@include LightingModel.slh@> +<@include LightPoint.slh@> +<$declareLightingPoint(supportScattering)$> <@include LightSpot.slh@> <$declareLightingSpot(supportScattering)$> -uniform vec4 texcoordFrameTransform; +//uniform vec4 texcoordFrameTransform; in vec4 _texCoord0; +//flat in int instanceID; out vec4 _fragColor; void main(void) { // DeferredFrameTransform deferredTransform = getDeferredFrameTransform(); // Grab the fragment data from the uv - vec2 texCoord = _texCoord0.st / _texCoord0.q; + vec2 texCoord = _texCoord0.st;/* / _texCoord0.q; texCoord *= texcoordFrameTransform.zw; - texCoord += texcoordFrameTransform.xy; + texCoord += texcoordFrameTransform.xy;*/ vec4 fragPosition = unpackDeferredPositionFromZeye(texCoord); - - // Need the light now - Light light = getLight(0); - - // Frag pos in world - mat4 invViewMat = getViewInverse(); - vec4 fragPos = invViewMat * fragPosition; - - // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space - vec4 fragLightVecLen2; - vec4 fragLightDirLen; - float cosSpotAngle; - if (!clipFragToLightVolumeSpot(light, fragPos.xyz, fragLightVecLen2, fragLightDirLen, cosSpotAngle)) { - discard; - } - - // _fragColor.rgb = vec3(0.0, 1.0, 1.0); - // return; - DeferredFragment frag = unpackDeferredFragmentNoPositionNoAmbient(texCoord); - // frag.depthVal = depthValue; - frag.position = fragPosition; if (frag.mode == FRAG_MODE_UNLIT) { discard; } - // Frag to eye vec - vec4 fragEyeVector = invViewMat * vec4(-frag.position.xyz, 0.0); - vec3 fragEyeDir = normalize(fragEyeVector.xyz); + // frag.depthVal = depthValue; + frag.position = fragPosition; - vec3 diffuse; - vec3 specular; vec4 midNormalCurvature; vec4 lowNormalCurvature; if (frag.mode == FRAG_MODE_SCATTERING) { unpackMidLowNormalCurvature(texCoord, midNormalCurvature, lowNormalCurvature); } - evalLightingSpot(diffuse, specular, light, - fragLightDirLen.xyzw, cosSpotAngle, fragEyeDir, frag.normal, frag.roughness, - frag.metallic, frag.fresnel, frag.albedo, 1.0, - frag.scattering, midNormalCurvature, lowNormalCurvature); - _fragColor.rgb += diffuse; - _fragColor.rgb += specular; + // Frag pos in world + mat4 invViewMat = getViewInverse(); + vec4 fragPos = invViewMat * fragPosition; - // _fragColor.rgb = vec3(0.0, 1.0, 1.0); + // Frag to eye vec + vec4 fragEyeVector = invViewMat * vec4(-frag.position.xyz, 0.0); + vec3 fragEyeDir = normalize(fragEyeVector.xyz); + + int numLights = lightIndex[0]; + for (int i = 0; i < numLights; i++) { + // Need the light now + Light light = getLight(lightIndex[i + 1]); + bool isSpot = light_isSpot(light); + // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space + vec4 fragLightVecLen2; + vec4 fragLightDirLen; + float cosSpotAngle; + if (isSpot) { + if (!clipFragToLightVolumeSpot(light, fragPos.xyz, fragLightVecLen2, fragLightDirLen, cosSpotAngle)) { + continue; + } + } else { + if (!clipFragToLightVolumePoint(light, fragPos.xyz, fragLightVecLen2)) { + continue; + } + } + + vec3 diffuse; + vec3 specular; + + if (isSpot) { + evalLightingSpot(diffuse, specular, light, + fragLightDirLen.xyzw, cosSpotAngle, fragEyeDir, frag.normal, frag.roughness, + frag.metallic, frag.fresnel, frag.albedo, 1.0, + frag.scattering, midNormalCurvature, lowNormalCurvature); + } else { + evalLightingPoint(diffuse, specular, light, + fragLightVecLen2.xyz, fragEyeDir, frag.normal, frag.roughness, + frag.metallic, frag.fresnel, frag.albedo, 1.0, + frag.scattering, midNormalCurvature, lowNormalCurvature); + } + + _fragColor.rgb += diffuse; + _fragColor.rgb += specular; + } } From 0c45627d9427989a3bf6cbb2378bbc970ff12d00 Mon Sep 17 00:00:00 2001 From: samcake Date: Tue, 6 Sep 2016 12:39:48 -0700 Subject: [PATCH 12/75] CLeaning up the code for the RenderableLightEntityItem --- .../src/RenderableLightEntityItem.cpp | 127 +++++++++++------- .../src/RenderableLightEntityItem.h | 90 ++----------- .../src/DeferredLightingEffect.cpp | 35 +++-- libraries/render-utils/src/LightPayload.cpp | 45 +++++++ libraries/render-utils/src/LightPayload.h | 41 ++++++ libraries/render-utils/src/spot_light.slf | 2 +- .../developer/utilities/render/statsGPU.qml | 41 ------ 7 files changed, 198 insertions(+), 183 deletions(-) create mode 100644 libraries/render-utils/src/LightPayload.cpp create mode 100644 libraries/render-utils/src/LightPayload.h diff --git a/libraries/entities-renderer/src/RenderableLightEntityItem.cpp b/libraries/entities-renderer/src/RenderableLightEntityItem.cpp index 4a62a5b652..eeb6914026 100644 --- a/libraries/entities-renderer/src/RenderableLightEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableLightEntityItem.cpp @@ -11,9 +11,7 @@ #include -#include -#include #include #include @@ -29,16 +27,68 @@ RenderableLightEntityItem::RenderableLightEntityItem(const EntityItemID& entityI { } -void RenderableLightEntityItem::updateLightFromEntity(render::PendingChanges& pendingChanges) { +bool RenderableLightEntityItem::addToScene(EntityItemPointer self, std::shared_ptr scene, render::PendingChanges& pendingChanges) { + _myItem = scene->allocateID(); + + auto renderItem = std::make_shared(); + updateRenderItemFromEntity(renderItem.get()); + + auto renderPayload = std::make_shared(renderItem); + + render::Item::Status::Getters statusGetters; + makeEntityItemStatusGetters(self, statusGetters); + renderPayload->addStatusGetters(statusGetters); + + pendingChanges.resetItem(_myItem, renderPayload); + + return true; +} + +void RenderableLightEntityItem::somethingChangedNotification() { + if (_lightPropertiesChanged) { + notifyChanged(); + } + LightEntityItem::somethingChangedNotification(); +} + +void RenderableLightEntityItem::removeFromScene(EntityItemPointer self, std::shared_ptr scene, render::PendingChanges& pendingChanges) { + pendingChanges.removeItem(_myItem); + render::Item::clearID(_myItem); +} + +void RenderableLightEntityItem::locationChanged(bool tellPhysics) { + EntityItem::locationChanged(tellPhysics); + notifyChanged(); +} + +void RenderableLightEntityItem::dimensionsChanged() { + EntityItem::dimensionsChanged(); + notifyChanged(); +} + +void RenderableLightEntityItem::checkFading() { + bool transparent = isTransparent(); + if (transparent != _prevIsTransparent) { + notifyChanged(); + _isFading = false; + _prevIsTransparent = transparent; + } +} + +void RenderableLightEntityItem::notifyChanged() { + if (!render::Item::isValidID(_myItem)) { return; } + render::PendingChanges pendingChanges; + render::ScenePointer scene = AbstractViewStateInterface::instance()->getMain3DScene(); - pendingChanges.updateItem(_myItem, [this](LightRenderItem& data) { - data.updateLightFromEntity(this); - }); + updateLightFromEntity(pendingChanges); + + scene->enqueuePendingChanges(pendingChanges); } + /* void RenderableLightEntityItem::render(RenderArgs* args) { PerformanceTimer perfTimer("RenderableLightEntityItem::render"); @@ -72,75 +122,54 @@ bool RenderableLightEntityItem::findDetailedRayIntersection(const glm::vec3& ori } - -namespace render { - template <> const ItemKey payloadGetKey(const LightRenderItem::Pointer& payload) { - return ItemKey::Builder::light(); +void RenderableLightEntityItem::updateLightFromEntity(render::PendingChanges& pendingChanges) { + if (!render::Item::isValidID(_myItem)) { + return; } - template <> const Item::Bound payloadGetBound(const LightRenderItem::Pointer& payload) { - if (payload) { - return payload->_bound; - } - return render::Item::Bound(); - } - template <> void payloadRender(const LightRenderItem::Pointer& payload, RenderArgs* args) { - if (args) { - if (payload) { - payload->render(args); - } - } - } + + pendingChanges.updateItem(_myItem, [this](LightPayload& data) { + this->updateRenderItemFromEntity(&data); + }); } -LightRenderItem::LightRenderItem() : -_light(std::make_shared()) -{ -} - -void LightRenderItem::updateLightFromEntity(RenderableLightEntityItem* entity) { - _light->setPosition(entity->getPosition()); - _light->setOrientation(entity->getRotation()); +void RenderableLightEntityItem::updateRenderItemFromEntity(LightPayload* lightPayload) { + auto entity = this; + auto light = lightPayload->editLight(); + light->setPosition(entity->getPosition()); + light->setOrientation(entity->getRotation()); bool success; - _bound = entity->getAABox(success); + lightPayload->editBound() = entity->getAABox(success); if (!success) { - _bound = render::Item::Bound(); + lightPayload->editBound() = render::Item::Bound(); } glm::vec3 dimensions = entity->getDimensions(); float largestDiameter = glm::max(dimensions.x, dimensions.y, dimensions.z); - _light->setMaximumRadius(largestDiameter / 2.0f); + light->setMaximumRadius(largestDiameter / 2.0f); - _light->setColor(toGlm(entity->getXColor())); + light->setColor(toGlm(entity->getXColor())); float intensity = entity->getIntensity();//* entity->getFadingRatio(); - _light->setIntensity(intensity); + light->setIntensity(intensity); - _light->setFalloffRadius(entity->getFalloffRadius()); + light->setFalloffRadius(entity->getFalloffRadius()); float exponent = entity->getExponent(); float cutoff = glm::radians(entity->getCutoff()); if (!entity->getIsSpotlight()) { - _light->setType(model::Light::POINT); + light->setType(model::Light::POINT); } else { - _light->setType(model::Light::SPOT); + light->setType(model::Light::SPOT); - _light->setSpotAngle(cutoff); - _light->setSpotExponent(exponent); + light->setSpotAngle(cutoff); + light->setSpotExponent(exponent); } } -void LightRenderItem::render(RenderArgs* args) { - - //updateLightFromEntity(); - - DependencyManager::get()->addLight(_light); - -} - diff --git a/libraries/entities-renderer/src/RenderableLightEntityItem.h b/libraries/entities-renderer/src/RenderableLightEntityItem.h index 883af056aa..d37fa30318 100644 --- a/libraries/entities-renderer/src/RenderableLightEntityItem.h +++ b/libraries/entities-renderer/src/RenderableLightEntityItem.h @@ -13,32 +13,9 @@ #define hifi_RenderableLightEntityItem_h #include -#include +#include #include "RenderableEntityItem.h" -class RenderableLightEntityItem; - -class LightRenderItem { -public: - using Payload = render::Payload; - using Pointer = Payload::DataPointer; - - model::LightPointer _light; - - render::Item::Bound _bound; - - LightRenderItem(); - void render(RenderArgs* args); - - void updateLightFromEntity(RenderableLightEntityItem* entity); - -}; - -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: @@ -53,67 +30,18 @@ public: void updateLightFromEntity(render::PendingChanges& pendingChanges); - virtual bool addToScene(EntityItemPointer self, std::shared_ptr scene, render::PendingChanges& pendingChanges) override { - _myItem = scene->allocateID(); + virtual bool addToScene(EntityItemPointer self, std::shared_ptr scene, render::PendingChanges& pendingChanges) override; - auto renderItem = std::make_shared(); - renderItem->updateLightFromEntity(this); + virtual void somethingChangedNotification() override; + virtual void removeFromScene(EntityItemPointer self, std::shared_ptr scene, render::PendingChanges& pendingChanges) override; - auto renderPayload = std::make_shared(renderItem); + virtual void locationChanged(bool tellPhysics = true) override; - render::Item::Status::Getters statusGetters; - makeEntityItemStatusGetters(self, statusGetters); - renderPayload->addStatusGetters(statusGetters); + virtual void dimensionsChanged() override; - pendingChanges.resetItem(_myItem, renderPayload); + void checkFading(); - return true; - } - - virtual void somethingChangedNotification() override { - if (_lightPropertiesChanged) { - notifyChanged(); - } - LightEntityItem::somethingChangedNotification(); - } - - 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); - notifyChanged(); - } - - virtual void dimensionsChanged() override { - EntityItem::dimensionsChanged(); - notifyChanged(); - } - - void checkFading() { - bool transparent = isTransparent(); - if (transparent != _prevIsTransparent) { - notifyChanged(); - _isFading = false; - _prevIsTransparent = transparent; - } - } - - void notifyChanged() { - - if (!render::Item::isValidID(_myItem)) { - return; - } - - render::PendingChanges pendingChanges; - render::ScenePointer scene = AbstractViewStateInterface::instance()->getMain3DScene(); - - updateLightFromEntity(pendingChanges); - - scene->enqueuePendingChanges(pendingChanges); - } + void notifyChanged(); private: bool _prevIsTransparent { isTransparent() }; @@ -121,6 +49,8 @@ private: // Dirty flag turn true when either setSubClassProperties or readEntitySubclassDataFromBuffer is changing a value + void updateRenderItemFromEntity(LightPayload* lightPayload); + }; diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index b7e34095c1..84ac7b2c9c 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -425,7 +425,6 @@ void PrepareDeferred::run(const SceneContextPointer& sceneContext, const RenderC outputs.edit0() = _deferredFramebuffer; outputs.edit1() = _deferredFramebuffer->getLightingFramebuffer(); - gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { batch.enableStereo(false); batch.setViewportTransform(args->_viewport); @@ -457,7 +456,8 @@ void RenderDeferredSetup::run(const render::SceneContextPointer& sceneContext, c const SubsurfaceScatteringResourcePointer& subsurfaceScatteringResource) { auto args = renderContext->args; - gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { + auto& batch = (*args->_batch); + // gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { // Framebuffer copy operations cannot function as multipass stereo operations. batch.enableStereo(false); @@ -567,7 +567,7 @@ void RenderDeferredSetup::run(const render::SceneContextPointer& sceneContext, c batch.setResourceTexture(SKYBOX_MAP_UNIT, nullptr); } batch.setResourceTexture(SHADOW_MAP_UNIT, nullptr); - }); + // }); } @@ -589,9 +589,10 @@ void RenderDeferredLocals::run(const render::SceneContextPointer& sceneContext, return; } auto args = renderContext->args; - gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { + auto& batch = (*args->_batch); + // gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { // Framebuffer copy operations cannot function as multipass stereo operations. - batch.enableStereo(false); + /// batch.enableStereo(false); // THe main viewport is assumed to be the mono viewport (or the 2 stereo faces side by side within that viewport) auto viewport = args->_viewport; @@ -730,12 +731,13 @@ void RenderDeferredLocals::run(const render::SceneContextPointer& sceneContext, } }*/ } - }); + // }); } void RenderDeferredCleanup::run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext) { auto args = renderContext->args; - gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { + auto& batch = (*args->_batch); + // gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { // Probably not necessary in the long run because the gpu layer would unbound this texture if used as render target batch.setResourceTexture(DEFERRED_BUFFER_COLOR_UNIT, nullptr); batch.setResourceTexture(DEFERRED_BUFFER_NORMAL_UNIT, nullptr); @@ -752,7 +754,7 @@ void RenderDeferredCleanup::run(const render::SceneContextPointer& sceneContext, batch.setUniformBuffer(SCATTERING_PARAMETERS_BUFFER_SLOT, nullptr); // batch.setUniformBuffer(LIGHTING_MODEL_BUFFER_SLOT, nullptr); batch.setUniformBuffer(DEFERRED_FRAME_TRANSFORM_BUFFER_SLOT, nullptr); - }); + // }); auto deferredLightingEffect = DependencyManager::get(); @@ -788,9 +790,14 @@ void RenderDeferred::run(const SceneContextPointer& sceneContext, const RenderCo _gpuTimer = std::make_shared < gpu::RangeTimer>(__FUNCTION__); } - gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { + auto previousBatch = args->_batch; + gpu::Batch batch; + // f(batch); + args->_batch = &batch; + + // gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { _gpuTimer->begin(batch); - }); + // }); setupJob.run(sceneContext, renderContext, deferredTransform, deferredFramebuffer, lightingModel, surfaceGeometryFramebuffer, ssaoFramebuffer, subsurfaceScatteringResource); @@ -798,10 +805,14 @@ void RenderDeferred::run(const SceneContextPointer& sceneContext, const RenderCo cleanupJob.run(sceneContext, renderContext); - gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { + // gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { _gpuTimer->end(batch); - }); + // }); + args->_context->appendFrameBatch(batch); + args->_batch = previousBatch; + + auto config = std::static_pointer_cast(renderContext->jobConfig); config->setGPUBatchRunTime(_gpuTimer->getGPUAverage(), _gpuTimer->getBatchAverage()); } diff --git a/libraries/render-utils/src/LightPayload.cpp b/libraries/render-utils/src/LightPayload.cpp new file mode 100644 index 0000000000..8bb9a57145 --- /dev/null +++ b/libraries/render-utils/src/LightPayload.cpp @@ -0,0 +1,45 @@ +// +// LightPayload.cpp +// +// Created by Sam Gateau on 9/6/16. +// Copyright 2016 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 "LightPayload.h" + + +#include +#include "DeferredLightingEffect.h" + + +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->editBound(); + } + return render::Item::Bound(); + } + template <> void payloadRender(const LightPayload::Pointer& payload, RenderArgs* args) { + if (args) { + if (payload) { + payload->render(args); + } + } + } +} + +LightPayload::LightPayload() : +_light(std::make_shared()) +{ +} + +void LightPayload::render(RenderArgs* args) { + + DependencyManager::get()->addLight(_light); +} \ No newline at end of file diff --git a/libraries/render-utils/src/LightPayload.h b/libraries/render-utils/src/LightPayload.h new file mode 100644 index 0000000000..2f065e4b5b --- /dev/null +++ b/libraries/render-utils/src/LightPayload.h @@ -0,0 +1,41 @@ +// +// LightPayload.h +// +// Created by Sam Gateau on 9/6/16. +// Copyright 2016 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_LightPayload_h +#define hifi_LightPayload_h + + +#include +#include + + +class LightPayload { +public: + using Payload = render::Payload; + using Pointer = Payload::DataPointer; + + LightPayload(); + void render(RenderArgs* args); + + model::LightPointer editLight() { return _light; } + render::Item::Bound& editBound() { return _bound; } + +protected: + model::LightPointer _light; + render::Item::Bound _bound; +}; + +namespace render { + template <> const ItemKey payloadGetKey(const LightPayload::Pointer& payload); + template <> const Item::Bound payloadGetBound(const LightPayload::Pointer& payload); + template <> void payloadRender(const LightPayload::Pointer& payload, RenderArgs* args); +} + +#endif \ No newline at end of file diff --git a/libraries/render-utils/src/spot_light.slf b/libraries/render-utils/src/spot_light.slf index 7e1ed9d01e..d12db826c0 100644 --- a/libraries/render-utils/src/spot_light.slf +++ b/libraries/render-utils/src/spot_light.slf @@ -47,7 +47,7 @@ void main(void) { texCoord += texcoordFrameTransform.xy;*/ vec4 fragPosition = unpackDeferredPositionFromZeye(texCoord); - DeferredFragment frag = unpackDeferredFragmentNoPositionNoAmbient(texCoord); + DeferredFragment frag = unpackDeferredFragmentNoPosition(texCoord); if (frag.mode == FRAG_MODE_UNLIT) { discard; diff --git a/scripts/developer/utilities/render/statsGPU.qml b/scripts/developer/utilities/render/statsGPU.qml index 4a6ec29e2f..3d23c2c6dc 100644 --- a/scripts/developer/utilities/render/statsGPU.qml +++ b/scripts/developer/utilities/render/statsGPU.qml @@ -109,47 +109,6 @@ Item { } ] } - - PlotPerf { - title: "Batch Timing" - height: parent.evalEvenHeight() - object: parent.drawOpaqueConfig - valueUnit: "ms" - valueScale: 1 - valueNumDigits: "4" - plots: [ - { - object: Render.getConfig("OpaqueRangeTimer"), - prop: "gpuBatchTime", - label: "Opaque", - color: "#FFFFFF" - }, - { - object: Render.getConfig("LinearDepth"), - prop: "gpuBatchTime", - label: "LinearDepth", - color: "#00FF00" - },{ - object: Render.getConfig("SurfaceGeometry"), - prop: "gpuBatchTime", - label: "SurfaceGeometry", - color: "#00FFFF" - }, - { - object: Render.getConfig("RenderDeferred"), - prop: "gpuBatchTime", - label: "DeferredLighting", - color: "#FF00FF" - } - , - { - object: Render.getConfig("ToneAndPostRangeTimer"), - prop: "gpuBatchTime", - label: "tone and post", - color: "#FF0000" - } - ] - } } } From 1165c54f671126713b5501f7be637897f4d95a93 Mon Sep 17 00:00:00 2001 From: samcake Date: Tue, 6 Sep 2016 16:24:03 -0700 Subject: [PATCH 13/75] cleaning up the IndexedContainer in its own file and removing warnings --- libraries/gpu/src/gpu/Buffer.h | 2 +- .../src/DeferredLightingEffect.cpp | 8 +- libraries/render-utils/src/LightStage.h | 145 +---------------- .../render/src/render/IndexedContainer.h | 150 ++++++++++++++++++ 4 files changed, 160 insertions(+), 145 deletions(-) create mode 100644 libraries/render/src/render/IndexedContainer.h diff --git a/libraries/gpu/src/gpu/Buffer.h b/libraries/gpu/src/gpu/Buffer.h index 981424de2f..047903a537 100644 --- a/libraries/gpu/src/gpu/Buffer.h +++ b/libraries/gpu/src/gpu/Buffer.h @@ -177,7 +177,7 @@ protected: public: using Size = Resource::Size; - using Index = int; + using Index = int32_t; BufferPointer _buffer; Size _offset { 0 }; diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index 84ac7b2c9c..55af6fd5de 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -257,12 +257,12 @@ model::MeshPointer DeferredLightingEffect::getPointLightMesh() { auto solid = geometry::icosahedron(); solid.fitDimension(1.05f); // scaled to 1.05 meters, it will be scaled by the shader accordingly to the light size - int verticesSize = solid.vertices.size() * 3 * sizeof(float); + int verticesSize = (int) (solid.vertices.size() * 3 * sizeof(float)); float* vertexData = (float*) solid.vertices.data(); _pointLightMesh->setVertexBuffer(gpu::BufferView(new gpu::Buffer(verticesSize, (gpu::Byte*) vertexData), gpu::Element::VEC3F_XYZ)); - auto nbIndices = solid.faces.size() * 3; + int nbIndices = (int) solid.faces.size() * 3; gpu::uint16* indexData = new gpu::uint16[nbIndices]; gpu::uint16* index = indexData; @@ -628,11 +628,11 @@ void RenderDeferredLocals::run(const render::SceneContextPointer& sceneContext, if (points && !srcPointLights.empty()) { memcpy(lightIndices.data() + (lightIndices[0] + 1), srcPointLights.data(), srcPointLights.size() * sizeof(int)); - lightIndices[0] += srcPointLights.size(); + lightIndices[0] += (int) srcPointLights.size(); } if (spots && !srcSpotLights.empty()) { memcpy(lightIndices.data() + (lightIndices[0] + 1), srcSpotLights.data(), srcSpotLights.size() * sizeof(int)); - lightIndices[0] += srcSpotLights.size(); + lightIndices[0] += (int) srcSpotLights.size(); } if (lightIndices[0] > 0) { diff --git a/libraries/render-utils/src/LightStage.h b/libraries/render-utils/src/LightStage.h index dc80375f36..4319eb80ba 100644 --- a/libraries/render-utils/src/LightStage.h +++ b/libraries/render-utils/src/LightStage.h @@ -14,6 +14,7 @@ #include #include +#include #include "gpu/Framebuffer.h" @@ -21,150 +22,14 @@ 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 - (Index) _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 Index = render::indexed_container::Index; + static const Index INVALID_INDEX { render::indexed_container::INVALID_INDEX }; using LightPointer = model::LightPointer; - using Lights = indexed_elements::IndexedPointerVector; + using Lights = render::indexed_container::IndexedPointerVector; using LightMap = std::unordered_map; class Shadow { @@ -202,7 +67,7 @@ public: friend class Light; }; using ShadowPointer = std::shared_ptr; - using Shadows = indexed_elements::IndexedPointerVector; + using Shadows = render::indexed_container::IndexedPointerVector; struct Desc { Index shadowId { INVALID_INDEX }; diff --git a/libraries/render/src/render/IndexedContainer.h b/libraries/render/src/render/IndexedContainer.h new file mode 100644 index 0000000000..c5357791d8 --- /dev/null +++ b/libraries/render/src/render/IndexedContainer.h @@ -0,0 +1,150 @@ +// +// IndexedContainer.h +// render +// +// Created by Sam Gateau on 9/6/2016. +// Copyright 2016 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_IndexedContainer_h +#define hifi_render_IndexedContainer_h + +#include + +namespace render { +namespace indexed_container { + + 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 - (Index) _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(); + } + } + }; +}; +} +#endif \ No newline at end of file From e2a9751cf5bed24498ce6882ade9b7161683e212 Mon Sep 17 00:00:00 2001 From: samcake Date: Tue, 6 Sep 2016 16:35:28 -0700 Subject: [PATCH 14/75] REmove warnings --- libraries/gpu/src/gpu/Buffer.h | 2 +- libraries/render-utils/src/LightStage.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/gpu/src/gpu/Buffer.h b/libraries/gpu/src/gpu/Buffer.h index 047903a537..3233dad8a9 100644 --- a/libraries/gpu/src/gpu/Buffer.h +++ b/libraries/gpu/src/gpu/Buffer.h @@ -60,7 +60,7 @@ public: // The size in bytes of data stored in the buffer Size getSize() const override; template - Size getTypedSize() const { return getSize() / sizeof(T); }; + Size getNumTypedElements() const { return getSize() / sizeof(T); }; const Byte* getData() const { return getSysmem().readData(); } diff --git a/libraries/render-utils/src/LightStage.cpp b/libraries/render-utils/src/LightStage.cpp index 8909284a02..bcdee5c0a9 100644 --- a/libraries/render-utils/src/LightStage.cpp +++ b/libraries/render-utils/src/LightStage.cpp @@ -106,7 +106,7 @@ LightStage::Index LightStage::addLight(const LightPointer& light) { if (lightId != INVALID_INDEX) { // Allocate the matching Desc to the light - if (lightId >= _descs.size()) { + if (lightId >= (Index) _descs.size()) { _descs.emplace_back(Desc()); } else { _descs.emplace(_descs.begin() + lightId, Desc()); @@ -131,7 +131,7 @@ void LightStage::updateLightArrayBuffer(Index lightId) { assert(checkLightId(lightId)); auto lightSize = sizeof(model::Light::Schema); - if (lightId > _lightArrayBuffer->getTypedSize()) { + if (lightId > (Index) _lightArrayBuffer->getNumTypedElements()) { _lightArrayBuffer->resize(lightSize * (lightId + 10)); } From 9bed047b752980bd7687e40266cc3f188a6730c2 Mon Sep 17 00:00:00 2001 From: samcake Date: Tue, 6 Sep 2016 16:42:01 -0700 Subject: [PATCH 15/75] Less warnings --- .../render-utils/src/DebugDeferredBuffer.cpp | 1 - .../src/DeferredLightingEffect.cpp | 132 +++--------------- 2 files changed, 17 insertions(+), 116 deletions(-) diff --git a/libraries/render-utils/src/DebugDeferredBuffer.cpp b/libraries/render-utils/src/DebugDeferredBuffer.cpp index 6278117b32..09dd4ff82a 100644 --- a/libraries/render-utils/src/DebugDeferredBuffer.cpp +++ b/libraries/render-utils/src/DebugDeferredBuffer.cpp @@ -388,7 +388,6 @@ void DebugDeferredBuffer::run(const SceneContextPointer& sceneContext, const Ren const auto geometryBuffer = DependencyManager::get(); const auto framebufferCache = DependencyManager::get(); const auto textureCache = DependencyManager::get(); - const auto& lightStage = DependencyManager::get()->getLightStage(); glm::mat4 projMat; Transform viewMat; diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index 55af6fd5de..99d1431f20 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -454,11 +454,10 @@ void RenderDeferredSetup::run(const render::SceneContextPointer& sceneContext, c const SurfaceGeometryFramebufferPointer& surfaceGeometryFramebuffer, const AmbientOcclusionFramebufferPointer& ambientOcclusionFramebuffer, const SubsurfaceScatteringResourcePointer& subsurfaceScatteringResource) { - + auto args = renderContext->args; auto& batch = (*args->_batch); - // gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { - + { // Framebuffer copy operations cannot function as multipass stereo operations. batch.enableStereo(false); @@ -567,8 +566,7 @@ void RenderDeferredSetup::run(const render::SceneContextPointer& sceneContext, c batch.setResourceTexture(SKYBOX_MAP_UNIT, nullptr); } batch.setResourceTexture(SHADOW_MAP_UNIT, nullptr); - // }); - + } } RenderDeferredLocals::RenderDeferredLocals() : @@ -590,10 +588,7 @@ void RenderDeferredLocals::run(const render::SceneContextPointer& sceneContext, } auto args = renderContext->args; auto& batch = (*args->_batch); - // gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { - // Framebuffer copy operations cannot function as multipass stereo operations. - /// batch.enableStereo(false); - + { // THe main viewport is assumed to be the mono viewport (or the 2 stereo faces side by side within that viewport) auto viewport = args->_viewport; @@ -617,9 +612,6 @@ void RenderDeferredLocals::run(const render::SceneContextPointer& sceneContext, auto textureFrameTransform = gpu::Framebuffer::evalSubregionTexcoordTransformCoefficients(deferredFramebuffer->getFrameSize(), viewport); - // batch.setProjectionTransform(projMat); - // batch.setViewTransform(viewTransform, true); - // gather lights auto& srcPointLights = deferredLightingEffect->_pointLights; auto& srcSpotLights = deferredLightingEffect->_spotLights; @@ -628,11 +620,11 @@ void RenderDeferredLocals::run(const render::SceneContextPointer& sceneContext, if (points && !srcPointLights.empty()) { memcpy(lightIndices.data() + (lightIndices[0] + 1), srcPointLights.data(), srcPointLights.size() * sizeof(int)); - lightIndices[0] += (int) srcPointLights.size(); + lightIndices[0] += (int)srcPointLights.size(); } if (spots && !srcSpotLights.empty()) { memcpy(lightIndices.data() + (lightIndices[0] + 1), srcSpotLights.data(), srcSpotLights.size() * sizeof(int)); - lightIndices[0] += (int) srcSpotLights.size(); + lightIndices[0] += (int)srcSpotLights.size(); } if (lightIndices[0] > 0) { @@ -641,103 +633,20 @@ void RenderDeferredLocals::run(const render::SceneContextPointer& sceneContext, // Spot light pipeline batch.setPipeline(deferredLightingEffect->_spotLight); - batch._glUniform4fv(deferredLightingEffect->_spotLightLocations->texcoordFrameTransform, 1, reinterpret_cast< const float* >(&textureFrameTransform)); - - // Spot mesh - auto mesh = deferredLightingEffect->getSpotLightMesh(); - batch.setIndexBuffer(mesh->getIndexBuffer()); - batch.setInputBuffer(0, mesh->getVertexBuffer()); - batch.setInputFormat(mesh->getVertexFormat()); - auto& conePart = mesh->getPartBuffer().get(0); - + batch._glUniform4fv(deferredLightingEffect->_spotLightLocations->texcoordFrameTransform, 1, reinterpret_cast(&textureFrameTransform)); + // Bind the global list of lights and the visible lights this frame batch.setUniformBuffer(deferredLightingEffect->_spotLightLocations->lightBufferUnit, deferredLightingEffect->getLightStage()._lightArrayBuffer); batch.setUniformBuffer(deferredLightingEffect->_spotLightLocations->lightIndexBufferUnit, _spotLightsBuffer); - // batch.drawIndexedInstanced(deferredLightingEffect->_spotLights.size(), model::Mesh::topologyToPrimitive(conePart._topology), conePart._numIndices, conePart._startIndex); - batch.draw(gpu::TRIANGLE_STRIP, 4); - /* - // Splat Point lights - if (points && !deferredLightingEffect->_pointLights.empty()) { - // POint light pipeline - batch.setPipeline(deferredLightingEffect->_pointLight); - batch._glUniform4fv(deferredLightingEffect->_pointLightLocations->texcoordFrameTransform, 1, reinterpret_cast< const float* >(&textureFrameTransform)); - - // Pojnt mesh - auto mesh = deferredLightingEffect->getPointLightMesh(); - batch.setIndexBuffer(mesh->getIndexBuffer()); - batch.setInputBuffer(0, mesh->getVertexBuffer()); - batch.setInputFormat(mesh->getVertexFormat()); - auto& spherePart = mesh->getPartBuffer().get(0); - - for (auto lightID : deferredLightingEffect->_pointLights) { - auto light = deferredLightingEffect->getLightStage().getLight(lightID); - if (!light) { - continue; - } - batch.setUniformBuffer(deferredLightingEffect->_pointLightLocations->lightBufferUnit, light->getSchemaBuffer()); - { - Transform model; - model.setTranslation(glm::vec3(light->getPosition().x, light->getPosition().y, light->getPosition().z)); - batch.setModelTransform(model); - - batch.drawIndexed(model::Mesh::topologyToPrimitive(spherePart._topology), spherePart._numIndices, spherePart._startIndex); - - } - } } - - - // Splat spot lights - if (spots && !deferredLightingEffect->_spotLights.empty()) { - std::vector again(deferredLightingEffect->_spotLights.size() + 1); - again[0] = deferredLightingEffect->_spotLights.size(); - memcpy(again.data() + 1, deferredLightingEffect->_spotLights.data(), deferredLightingEffect->_spotLights.size() * sizeof(int)); - _spotLightsBuffer._buffer->setData(again.size() * sizeof(int), (const gpu::Byte*) again.data()); - _spotLightsBuffer._size = again.size() * sizeof(int); - - // Spot light pipeline - batch.setPipeline(deferredLightingEffect->_spotLight); - batch._glUniform4fv(deferredLightingEffect->_spotLightLocations->texcoordFrameTransform, 1, reinterpret_cast< const float* >(&textureFrameTransform)); - - // Spot mesh - auto mesh = deferredLightingEffect->getSpotLightMesh(); - batch.setIndexBuffer(mesh->getIndexBuffer()); - batch.setInputBuffer(0, mesh->getVertexBuffer()); - batch.setInputFormat(mesh->getVertexFormat()); - auto& conePart = mesh->getPartBuffer().get(0); - - - batch.setUniformBuffer(deferredLightingEffect->_spotLightLocations->lightBufferUnit, deferredLightingEffect->getLightStage()._lightArrayBuffer); - batch.setUniformBuffer(deferredLightingEffect->_spotLightLocations->lightIndexBufferUnit, _spotLightsBuffer); - // batch.drawIndexedInstanced(deferredLightingEffect->_spotLights.size(), model::Mesh::topologyToPrimitive(conePart._topology), conePart._numIndices, conePart._startIndex); - - batch.draw(gpu::TRIANGLE_STRIP, 4); - /* - for (auto lightID : deferredLightingEffect->_spotLights) { - auto light = deferredLightingEffect->getLightStage().getLight(lightID); - if (!light) { - continue; - } - batch.setUniformBuffer(deferredLightingEffect->_spotLightLocations->lightBufferUnit, light->getSchemaBuffer()); - { - - Transform model; - model.setTranslation(light->getPosition()); - model.postRotate(light->getOrientation()); - batch.setModelTransform(model); - - batch.drawIndexed(model::Mesh::topologyToPrimitive(conePart._topology), conePart._numIndices, conePart._startIndex); - } - }*/ - } - // }); + } } void RenderDeferredCleanup::run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext) { auto args = renderContext->args; auto& batch = (*args->_batch); - // gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { + { // Probably not necessary in the long run because the gpu layer would unbound this texture if used as render target batch.setResourceTexture(DEFERRED_BUFFER_COLOR_UNIT, nullptr); batch.setResourceTexture(DEFERRED_BUFFER_NORMAL_UNIT, nullptr); @@ -750,12 +659,12 @@ void RenderDeferredCleanup::run(const render::SceneContextPointer& sceneContext, batch.setResourceTexture(DEFERRED_BUFFER_DIFFUSED_CURVATURE_UNIT, nullptr); batch.setResourceTexture(SCATTERING_LUT_UNIT, nullptr); batch.setResourceTexture(SCATTERING_SPECULAR_UNIT, nullptr); - + batch.setUniformBuffer(SCATTERING_PARAMETERS_BUFFER_SLOT, nullptr); - // batch.setUniformBuffer(LIGHTING_MODEL_BUFFER_SLOT, nullptr); + // batch.setUniformBuffer(LIGHTING_MODEL_BUFFER_SLOT, nullptr); batch.setUniformBuffer(DEFERRED_FRAME_TRANSFORM_BUFFER_SLOT, nullptr); - // }); - + } + auto deferredLightingEffect = DependencyManager::get(); // End of the Lighting pass @@ -792,23 +701,16 @@ void RenderDeferred::run(const SceneContextPointer& sceneContext, const RenderCo auto previousBatch = args->_batch; gpu::Batch batch; - // f(batch); args->_batch = &batch; - - // gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { - _gpuTimer->begin(batch); - // }); + _gpuTimer->begin(batch); setupJob.run(sceneContext, renderContext, deferredTransform, deferredFramebuffer, lightingModel, surfaceGeometryFramebuffer, ssaoFramebuffer, subsurfaceScatteringResource); lightsJob.run(sceneContext, renderContext, deferredTransform, deferredFramebuffer, lightingModel, surfaceGeometryFramebuffer); cleanupJob.run(sceneContext, renderContext); - - // gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { - _gpuTimer->end(batch); - // }); - + + _gpuTimer->end(batch); args->_context->appendFrameBatch(batch); args->_batch = previousBatch; From edb456aa8f7d049b59c2c6545936a31d65d0b169 Mon Sep 17 00:00:00 2001 From: samcake Date: Tue, 6 Sep 2016 17:16:54 -0700 Subject: [PATCH 16/75] ANd again --- libraries/render/src/render/IndexedContainer.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/render/src/render/IndexedContainer.h b/libraries/render/src/render/IndexedContainer.h index c5357791d8..847fb53bdf 100644 --- a/libraries/render/src/render/IndexedContainer.h +++ b/libraries/render/src/render/IndexedContainer.h @@ -78,7 +78,7 @@ namespace indexed_container { Index newElement(const Element& e) { Index index = _allocator.allocateIndex(); if (index != INVALID_INDEX) { - if (index < _elements.size()) { + if (index < (Index) _elements.size()) { _elements.emplace(_elements.begin() + index, e); } else { assert(index == _elements.size()); From 665a79f10033748fd8bc2e024e16e9ba2bb90a11 Mon Sep 17 00:00:00 2001 From: samcake Date: Tue, 6 Sep 2016 18:59:26 -0700 Subject: [PATCH 17/75] Creating a separate shader for the locallighting pass --- .../src/DeferredLightingEffect.cpp | 16 +-- .../render-utils/src/DeferredLightingEffect.h | 5 +- .../render-utils/src/local_lights_shading.slf | 102 ++++++++++++++++++ 3 files changed, 115 insertions(+), 8 deletions(-) create mode 100644 libraries/render-utils/src/local_lights_shading.slf diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index 99d1431f20..49979180b3 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -35,6 +35,7 @@ #include "directional_ambient_light_shadow_frag.h" #include "directional_skybox_light_shadow_frag.h" +#include "local_lights_shading_frag.h" #include "point_light_frag.h" #include "spot_light_frag.h" @@ -96,6 +97,7 @@ void DeferredLightingEffect::init() { loadLightProgram(deferred_light_vert, directional_ambient_light_shadow_frag, false, _directionalAmbientSphereLightShadow, _directionalAmbientSphereLightShadowLocations); loadLightProgram(deferred_light_vert, directional_skybox_light_shadow_frag, false, _directionalSkyboxLightShadow, _directionalSkyboxLightShadowLocations); + loadLightProgram(deferred_light_vert, local_lights_shading_frag, false, _localLight, _localLightLocations); loadLightProgram(deferred_light_limited_vert, point_light_frag, true, _pointLight, _pointLightLocations); loadLightProgram(deferred_light_vert, spot_light_frag, false, _spotLight, _spotLightLocations); @@ -570,7 +572,7 @@ void RenderDeferredSetup::run(const render::SceneContextPointer& sceneContext, c } RenderDeferredLocals::RenderDeferredLocals() : -_spotLightsBuffer(std::make_shared()) { +_localLightsBuffer(std::make_shared()) { } @@ -628,16 +630,16 @@ void RenderDeferredLocals::run(const render::SceneContextPointer& sceneContext, } if (lightIndices[0] > 0) { - _spotLightsBuffer._buffer->setData(lightIndices.size() * sizeof(int), (const gpu::Byte*) lightIndices.data()); - _spotLightsBuffer._size = lightIndices.size() * sizeof(int); + _localLightsBuffer._buffer->setData(lightIndices.size() * sizeof(int), (const gpu::Byte*) lightIndices.data()); + _localLightsBuffer._size = lightIndices.size() * sizeof(int); // Spot light pipeline - batch.setPipeline(deferredLightingEffect->_spotLight); - batch._glUniform4fv(deferredLightingEffect->_spotLightLocations->texcoordFrameTransform, 1, reinterpret_cast(&textureFrameTransform)); + batch.setPipeline(deferredLightingEffect->_localLight); + batch._glUniform4fv(deferredLightingEffect->_localLightLocations->texcoordFrameTransform, 1, reinterpret_cast(&textureFrameTransform)); // Bind the global list of lights and the visible lights this frame - batch.setUniformBuffer(deferredLightingEffect->_spotLightLocations->lightBufferUnit, deferredLightingEffect->getLightStage()._lightArrayBuffer); - batch.setUniformBuffer(deferredLightingEffect->_spotLightLocations->lightIndexBufferUnit, _spotLightsBuffer); + batch.setUniformBuffer(deferredLightingEffect->_localLightLocations->lightBufferUnit, deferredLightingEffect->getLightStage()._lightArrayBuffer); + batch.setUniformBuffer(deferredLightingEffect->_localLightLocations->lightIndexBufferUnit, _localLightsBuffer); batch.draw(gpu::TRIANGLE_STRIP, 4); } } diff --git a/libraries/render-utils/src/DeferredLightingEffect.h b/libraries/render-utils/src/DeferredLightingEffect.h index 1d0eb1cb15..0cff4c355c 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.h +++ b/libraries/render-utils/src/DeferredLightingEffect.h @@ -86,6 +86,8 @@ private: gpu::PipelinePointer _directionalAmbientSphereLightShadow; gpu::PipelinePointer _directionalLightShadow; + gpu::PipelinePointer _localLight; + gpu::PipelinePointer _pointLight; gpu::PipelinePointer _spotLight; @@ -97,6 +99,7 @@ private: LightLocationsPtr _directionalAmbientSphereLightShadowLocations; LightLocationsPtr _directionalLightShadowLocations; + LightLocationsPtr _localLightLocations; LightLocationsPtr _pointLightLocations; LightLocationsPtr _spotLightLocations; @@ -159,7 +162,7 @@ public: const LightingModelPointer& lightingModel, const SurfaceGeometryFramebufferPointer& surfaceGeometryFramebuffer); - gpu::BufferView _spotLightsBuffer; + gpu::BufferView _localLightsBuffer; RenderDeferredLocals(); diff --git a/libraries/render-utils/src/local_lights_shading.slf b/libraries/render-utils/src/local_lights_shading.slf new file mode 100644 index 0000000000..d5a759d7c0 --- /dev/null +++ b/libraries/render-utils/src/local_lights_shading.slf @@ -0,0 +1,102 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// local_lights_shading.frag +// fragment shader +// +// Created by Sam Gateau on 9/6/2016. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +// Everything about deferred buffer +<@include DeferredBufferRead.slh@> + +<$declareDeferredCurvature()$> + +// Everything about light +<@include model/Light.slh@> +<$declareLightBuffer(32)$> +uniform lightIndexBuffer { + int lightIndex[32]; +}; +<@include LightingModel.slh@> + +<@include LightPoint.slh@> +<$declareLightingPoint(supportScattering)$> +<@include LightSpot.slh@> +<$declareLightingSpot(supportScattering)$> + +in vec4 _texCoord0; +out vec4 _fragColor; + +void main(void) { + + // Grab the fragment data from the uv + vec2 texCoord = _texCoord0.st; + + vec4 fragPosition = unpackDeferredPositionFromZeye(texCoord); + DeferredFragment frag = unpackDeferredFragmentNoPosition(texCoord); + + if (frag.mode == FRAG_MODE_UNLIT) { + discard; + } + + frag.position = fragPosition; + + vec4 midNormalCurvature; + vec4 lowNormalCurvature; + if (frag.mode == FRAG_MODE_SCATTERING) { + unpackMidLowNormalCurvature(texCoord, midNormalCurvature, lowNormalCurvature); + } + + // Frag pos in world + mat4 invViewMat = getViewInverse(); + vec4 fragPos = invViewMat * fragPosition; + + // Frag to eye vec + vec4 fragEyeVector = invViewMat * vec4(-frag.position.xyz, 0.0); + vec3 fragEyeDir = normalize(fragEyeVector.xyz); + + int numLights = lightIndex[0]; + for (int i = 0; i < numLights; i++) { + // Need the light now + Light light = getLight(lightIndex[i + 1]); + bool isSpot = light_isSpot(light); + // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space + vec4 fragLightVecLen2; + vec4 fragLightDirLen; + float cosSpotAngle; + if (isSpot) { + if (!clipFragToLightVolumeSpot(light, fragPos.xyz, fragLightVecLen2, fragLightDirLen, cosSpotAngle)) { + continue; + } + } else { + if (!clipFragToLightVolumePoint(light, fragPos.xyz, fragLightVecLen2)) { + continue; + } + } + + vec3 diffuse; + vec3 specular; + + if (isSpot) { + evalLightingSpot(diffuse, specular, light, + fragLightDirLen.xyzw, cosSpotAngle, fragEyeDir, frag.normal, frag.roughness, + frag.metallic, frag.fresnel, frag.albedo, 1.0, + frag.scattering, midNormalCurvature, lowNormalCurvature); + } else { + evalLightingPoint(diffuse, specular, light, + fragLightVecLen2.xyz, fragEyeDir, frag.normal, frag.roughness, + frag.metallic, frag.fresnel, frag.albedo, 1.0, + frag.scattering, midNormalCurvature, lowNormalCurvature); + } + + _fragColor.rgb += diffuse; + _fragColor.rgb += specular; + } +} + From 34f40e08285ef626d28d21dd39c422d52a771247 Mon Sep 17 00:00:00 2001 From: samcake Date: Tue, 6 Sep 2016 19:01:13 -0700 Subject: [PATCH 18/75] Creating a separate shader for the locallighting pass --- libraries/render-utils/src/DeferredLightingEffect.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index 49979180b3..8f0e7ace83 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -86,6 +86,7 @@ void DeferredLightingEffect::init() { _directionalAmbientSphereLightShadowLocations = std::make_shared(); _directionalSkyboxLightShadowLocations = std::make_shared(); + _localLightLocations = std::make_shared(); _pointLightLocations = std::make_shared(); _spotLightLocations = std::make_shared(); From 139ba1b71c42cc816cbd73c17e77ffd0bdf790ea Mon Sep 17 00:00:00 2001 From: samcake Date: Wed, 7 Sep 2016 14:56:01 -0700 Subject: [PATCH 19/75] REnaming the shaders correctly --- .../src/DeferredLightingEffect.cpp | 139 +++++++++++++++++- .../render-utils/src/DeferredLightingEffect.h | 6 +- ...t_limited.slv => deferred_light_point.slv} | 11 +- .../render-utils/src/deferred_light_spot.slv | 4 +- libraries/render-utils/src/point_light.slf | 8 +- libraries/render-utils/src/spot_light.slf | 17 ++- tests/shaders/src/main.cpp | 7 +- 7 files changed, 166 insertions(+), 26 deletions(-) rename libraries/render-utils/src/{deferred_light_limited.slv => deferred_light_point.slv} (82%) diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index 8f0e7ace83..4f14b76ac0 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -24,7 +24,7 @@ #include "FramebufferCache.h" #include "deferred_light_vert.h" -#include "deferred_light_limited_vert.h" +#include "deferred_light_point_vert.h" #include "deferred_light_spot_vert.h" #include "directional_light_frag.h" @@ -76,6 +76,7 @@ enum DeferredShader_BufferSlot { }; static void loadLightProgram(const char* vertSource, const char* fragSource, bool lightVolume, gpu::PipelinePointer& program, LightLocationsPtr& locations); +static void loadLightVolumeProgram(const char* vertSource, const char* fragSource, bool front, gpu::PipelinePointer& program, LightLocationsPtr& locations); void DeferredLightingEffect::init() { _directionalLightLocations = std::make_shared(); @@ -99,8 +100,11 @@ void DeferredLightingEffect::init() { loadLightProgram(deferred_light_vert, directional_skybox_light_shadow_frag, false, _directionalSkyboxLightShadow, _directionalSkyboxLightShadowLocations); loadLightProgram(deferred_light_vert, local_lights_shading_frag, false, _localLight, _localLightLocations); - loadLightProgram(deferred_light_limited_vert, point_light_frag, true, _pointLight, _pointLightLocations); - loadLightProgram(deferred_light_vert, spot_light_frag, false, _spotLight, _spotLightLocations); + + loadLightVolumeProgram(deferred_light_point_vert, point_light_frag, false, _pointLightBack, _pointLightLocations); + loadLightVolumeProgram(deferred_light_point_vert, point_light_frag, true, _pointLightFront, _pointLightLocations); + loadLightVolumeProgram(deferred_light_spot_vert, spot_light_frag, false, _spotLightBack, _spotLightLocations); + loadLightVolumeProgram(deferred_light_spot_vert, spot_light_frag, true, _spotLightFront, _spotLightLocations); // Allocate a global light representing the Global Directional light casting shadow (the sun) and the ambient light _allocatedLights.push_back(std::make_shared()); @@ -240,6 +244,77 @@ static void loadLightProgram(const char* vertSource, const char* fragSource, boo } + +static void loadLightVolumeProgram(const char* vertSource, const char* fragSource, bool front, gpu::PipelinePointer& pipeline, LightLocationsPtr& locations) { + auto VS = gpu::Shader::createVertex(std::string(vertSource)); + auto PS = gpu::Shader::createPixel(std::string(fragSource)); + + gpu::ShaderPointer program = gpu::Shader::createProgram(VS, PS); + + gpu::Shader::BindingSet slotBindings; + slotBindings.insert(gpu::Shader::Binding(std::string("colorMap"), DEFERRED_BUFFER_COLOR_UNIT)); + slotBindings.insert(gpu::Shader::Binding(std::string("normalMap"), DEFERRED_BUFFER_NORMAL_UNIT)); + slotBindings.insert(gpu::Shader::Binding(std::string("specularMap"), DEFERRED_BUFFER_EMISSIVE_UNIT)); + slotBindings.insert(gpu::Shader::Binding(std::string("depthMap"), DEFERRED_BUFFER_DEPTH_UNIT)); + slotBindings.insert(gpu::Shader::Binding(std::string("obscuranceMap"), DEFERRED_BUFFER_OBSCURANCE_UNIT)); + slotBindings.insert(gpu::Shader::Binding(std::string("shadowMap"), SHADOW_MAP_UNIT)); + slotBindings.insert(gpu::Shader::Binding(std::string("skyboxMap"), SKYBOX_MAP_UNIT)); + + slotBindings.insert(gpu::Shader::Binding(std::string("linearZeyeMap"), DEFERRED_BUFFER_LINEAR_DEPTH_UNIT)); + slotBindings.insert(gpu::Shader::Binding(std::string("curvatureMap"), DEFERRED_BUFFER_CURVATURE_UNIT)); + slotBindings.insert(gpu::Shader::Binding(std::string("diffusedCurvatureMap"), DEFERRED_BUFFER_DIFFUSED_CURVATURE_UNIT)); + slotBindings.insert(gpu::Shader::Binding(std::string("scatteringLUT"), SCATTERING_LUT_UNIT)); + slotBindings.insert(gpu::Shader::Binding(std::string("scatteringSpecularBeckmann"), SCATTERING_SPECULAR_UNIT)); + + + slotBindings.insert(gpu::Shader::Binding(std::string("cameraCorrectionBuffer"), CAMERA_CORRECTION_BUFFER_SLOT)); + slotBindings.insert(gpu::Shader::Binding(std::string("deferredFrameTransformBuffer"), DEFERRED_FRAME_TRANSFORM_BUFFER_SLOT)); + slotBindings.insert(gpu::Shader::Binding(std::string("lightingModelBuffer"), LIGHTING_MODEL_BUFFER_SLOT)); + slotBindings.insert(gpu::Shader::Binding(std::string("subsurfaceScatteringParametersBuffer"), SCATTERING_PARAMETERS_BUFFER_SLOT)); + slotBindings.insert(gpu::Shader::Binding(std::string("lightBuffer"), LIGHT_GPU_SLOT)); + slotBindings.insert(gpu::Shader::Binding(std::string("lightIndexBuffer"), LIGHT_INDEX_GPU_SLOT)); + + + gpu::Shader::makeProgram(*program, slotBindings); + + locations->radius = program->getUniforms().findLocation("radius"); + locations->ambientSphere = program->getUniforms().findLocation("ambientSphere.L00"); + + locations->texcoordFrameTransform = program->getUniforms().findLocation("texcoordFrameTransform"); + + locations->lightBufferUnit = program->getBuffers().findLocation("lightBuffer"); + locations->lightIndexBufferUnit = program->getBuffers().findLocation("lightIndexBuffer"); + locations->deferredFrameTransformBuffer = program->getBuffers().findLocation("deferredFrameTransformBuffer"); + locations->subsurfaceScatteringParametersBuffer = program->getBuffers().findLocation("subsurfaceScatteringParametersBuffer"); + locations->shadowTransformBuffer = program->getBuffers().findLocation("shadowTransformBuffer"); + + auto state = std::make_shared(); + state->setColorWriteMask(true, true, true, false); + // state->setColorWriteMask(false, false, false, false); + + // Stencil test all the light passes for objects pixels only, not the background + + if (front) { + state->setCullMode(gpu::State::CULL_FRONT); + state->setDepthTest(true, false, gpu::LESS_EQUAL); + state->setStencilTest(true, 0xFF, gpu::State::StencilTest(0, 0xFF, gpu::ALWAYS, gpu::State::STENCIL_OP_INCR, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_INCR)); + + //state->setDepthClampEnable(true); + // TODO: We should use DepthClamp and avoid changing geometry for inside /outside cases + // additive blending + // state->setBlendFunction(true, gpu::State::ONE, gpu::State::BLEND_OP_ADD, gpu::State::ONE); + + } else { + state->setCullMode(gpu::State::CULL_BACK); + state->setDepthTest(true, false, gpu::GREATER_EQUAL); + state->setStencilTest(true, 0xFF, gpu::State::StencilTest(0, 0xFF, gpu::ALWAYS, gpu::State::STENCIL_OP_INCR, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_INCR)); + // additive blending + // state->setBlendFunction(true, gpu::State::ONE, gpu::State::BLEND_OP_ADD, gpu::State::ONE); + } + pipeline = gpu::Pipeline::create(program, state); + +} + void DeferredLightingEffect::setGlobalLight(const model::LightPointer& light) { auto globalLight = _allocatedLights.front(); globalLight->setDirection(light->getDirection()); @@ -618,7 +693,12 @@ void RenderDeferredLocals::run(const render::SceneContextPointer& sceneContext, // gather lights auto& srcPointLights = deferredLightingEffect->_pointLights; auto& srcSpotLights = deferredLightingEffect->_spotLights; - std::vector lightIndices(srcPointLights.size() + srcSpotLights.size() + 1); + int numPointLights = (int) srcPointLights.size(); + int offsetPointLights = 0; + int numSpotLights = (int) srcSpotLights.size(); + int offsetSpotLights = numPointLights; + + std::vector lightIndices(numPointLights + numSpotLights + 1); lightIndices[0] = 0; if (points && !srcPointLights.empty()) { @@ -634,13 +714,56 @@ void RenderDeferredLocals::run(const render::SceneContextPointer& sceneContext, _localLightsBuffer._buffer->setData(lightIndices.size() * sizeof(int), (const gpu::Byte*) lightIndices.data()); _localLightsBuffer._size = lightIndices.size() * sizeof(int); - // Spot light pipeline - batch.setPipeline(deferredLightingEffect->_localLight); - batch._glUniform4fv(deferredLightingEffect->_localLightLocations->texcoordFrameTransform, 1, reinterpret_cast(&textureFrameTransform)); - // Bind the global list of lights and the visible lights this frame batch.setUniformBuffer(deferredLightingEffect->_localLightLocations->lightBufferUnit, deferredLightingEffect->getLightStage()._lightArrayBuffer); batch.setUniformBuffer(deferredLightingEffect->_localLightLocations->lightIndexBufferUnit, _localLightsBuffer); + + + // before we get to the real lighting, let s try to cull down the number of pixels + { + /* if (numPointLights > 0) { + auto mesh = deferredLightingEffect->getPointLightMesh(); + batch.setIndexBuffer(mesh->getIndexBuffer()); + batch.setInputBuffer(0, mesh->getVertexBuffer()); + batch.setInputFormat(mesh->getVertexFormat()); + auto& pointPart = mesh->getPartBuffer().get(0); + + // Point light pipeline + batch.setPipeline(deferredLightingEffect->_pointLightBack); + batch._glUniform4fv(deferredLightingEffect->_pointLightLocations->texcoordFrameTransform, 1, reinterpret_cast(&textureFrameTransform)); + + batch.drawIndexedInstanced(numPointLights, model::Mesh::topologyToPrimitive(pointPart._topology), pointPart._numIndices, pointPart._startIndex, offsetPointLights); + + batch.setPipeline(deferredLightingEffect->_pointLightFront); + batch._glUniform4fv(deferredLightingEffect->_pointLightLocations->texcoordFrameTransform, 1, reinterpret_cast(&textureFrameTransform)); + + batch.drawIndexedInstanced(numPointLights, model::Mesh::topologyToPrimitive(pointPart._topology), pointPart._numIndices, pointPart._startIndex, offsetPointLights); + } */ + /* + if (numSpotLights > 0) { + auto mesh = deferredLightingEffect->getSpotLightMesh(); + batch.setIndexBuffer(mesh->getIndexBuffer()); + batch.setInputBuffer(0, mesh->getVertexBuffer()); + batch.setInputFormat(mesh->getVertexFormat()); + auto& conePart = mesh->getPartBuffer().get(0); + + // Spot light pipeline + batch.setPipeline(deferredLightingEffect->_spotLightBack); + batch._glUniform4fv(deferredLightingEffect->_spotLightLocations->texcoordFrameTransform, 1, reinterpret_cast(&textureFrameTransform)); + + batch.drawIndexedInstanced(numSpotLights, model::Mesh::topologyToPrimitive(conePart._topology), conePart._numIndices, conePart._startIndex, offsetSpotLights); + + batch.setPipeline(deferredLightingEffect->_spotLightFront); + batch._glUniform4fv(deferredLightingEffect->_spotLightLocations->texcoordFrameTransform, 1, reinterpret_cast(&textureFrameTransform)); + + batch.drawIndexedInstanced(numSpotLights, model::Mesh::topologyToPrimitive(conePart._topology), conePart._numIndices, conePart._startIndex, offsetSpotLights); + }*/ + } + + // Local light pipeline + batch.setPipeline(deferredLightingEffect->_localLight); + batch._glUniform4fv(deferredLightingEffect->_localLightLocations->texcoordFrameTransform, 1, reinterpret_cast(&textureFrameTransform)); + batch.draw(gpu::TRIANGLE_STRIP, 4); } } diff --git a/libraries/render-utils/src/DeferredLightingEffect.h b/libraries/render-utils/src/DeferredLightingEffect.h index 0cff4c355c..cbf5ff6ab3 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.h +++ b/libraries/render-utils/src/DeferredLightingEffect.h @@ -88,8 +88,10 @@ private: gpu::PipelinePointer _localLight; - gpu::PipelinePointer _pointLight; - gpu::PipelinePointer _spotLight; + gpu::PipelinePointer _pointLightBack; + gpu::PipelinePointer _pointLightFront; + gpu::PipelinePointer _spotLightBack; + gpu::PipelinePointer _spotLightFront; LightLocationsPtr _directionalSkyboxLightLocations; LightLocationsPtr _directionalAmbientSphereLightLocations; diff --git a/libraries/render-utils/src/deferred_light_limited.slv b/libraries/render-utils/src/deferred_light_point.slv similarity index 82% rename from libraries/render-utils/src/deferred_light_limited.slv rename to libraries/render-utils/src/deferred_light_point.slv index 4598447335..f6d4de3954 100644 --- a/libraries/render-utils/src/deferred_light_limited.slv +++ b/libraries/render-utils/src/deferred_light_point.slv @@ -19,14 +19,21 @@ <$declareStandardTransform()$> <@include model/Light.slh@> -<$declareLightBuffer()$> +<$declareLightBuffer(120)$> + +uniform lightIndexBuffer { + int lightIndex[120]; +}; out vec4 _texCoord0; void main(void) { + + instanceID = lightIndex[gl_InstanceID]; + Light light = getLight(instanceID); vec4 sphereVertex = inPosition; - vec4 sphereParam = getLightVolumeGeometry(getLight()); + vec4 sphereParam = getLightVolumeGeometry(light); sphereVertex.xyz *= sphereParam.w; diff --git a/libraries/render-utils/src/deferred_light_spot.slv b/libraries/render-utils/src/deferred_light_spot.slv index e99142d8ea..cd70724e1f 100755 --- a/libraries/render-utils/src/deferred_light_spot.slv +++ b/libraries/render-utils/src/deferred_light_spot.slv @@ -19,10 +19,10 @@ <$declareStandardTransform()$> <@include model/Light.slh@> -<$declareLightBuffer(32)$> +<$declareLightBuffer(120)$> uniform lightIndexBuffer { - int lightIndex[32]; + int lightIndex[120]; }; out vec4 _texCoord0; flat out int instanceID; diff --git a/libraries/render-utils/src/point_light.slf b/libraries/render-utils/src/point_light.slf index 018d6ca79b..239cbd5c91 100644 --- a/libraries/render-utils/src/point_light.slf +++ b/libraries/render-utils/src/point_light.slf @@ -11,7 +11,7 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // - + @@ -29,10 +29,13 @@ uniform vec4 texcoordFrameTransform; -in vec4 _texCoord0; +in vec4 _texCoord0;!> out vec4 _fragColor; void main(void) { + _fragColor = vec4(1.0, 1.0, 1.0, 1.0); + + } diff --git a/libraries/render-utils/src/spot_light.slf b/libraries/render-utils/src/spot_light.slf index d12db826c0..9d71832f15 100644 --- a/libraries/render-utils/src/spot_light.slf +++ b/libraries/render-utils/src/spot_light.slf @@ -13,7 +13,7 @@ // // Everything about deferred buffer -<@include DeferredBufferRead.slh@> + <$declareDeferredCurvature()$> @@ -31,21 +31,23 @@ uniform lightIndexBuffer { <$declareLightingSpot(supportScattering)$> //uniform vec4 texcoordFrameTransform; +!> - -in vec4 _texCoord0; +//in vec4 _texCoord0; //flat in int instanceID; out vec4 _fragColor; void main(void) { + _fragColor = vec4(1.0, 1.0, 1.0, 1.0); + // DeferredFrameTransform deferredTransform = getDeferredFrameTransform(); - + // Grab the fragment data from the uv - vec2 texCoord = _texCoord0.st;/* / _texCoord0.q; - texCoord *= texcoordFrameTransform.zw; + //vec2 texCoord = _texCoord0.st;/* / _texCoord0.q; + /*texCoord *= texcoordFrameTransform.zw; texCoord += texcoordFrameTransform.xy;*/ - + /* vec4 fragPosition = unpackDeferredPositionFromZeye(texCoord); DeferredFragment frag = unpackDeferredFragmentNoPosition(texCoord); @@ -108,5 +110,6 @@ void main(void) { _fragColor.rgb += diffuse; _fragColor.rgb += specular; } + */ } diff --git a/tests/shaders/src/main.cpp b/tests/shaders/src/main.cpp index 9744d8c78d..8a239f0728 100644 --- a/tests/shaders/src/main.cpp +++ b/tests/shaders/src/main.cpp @@ -28,7 +28,8 @@ #include #include -#include +#include +#include #include #include @@ -157,8 +158,8 @@ void QTestWindow::draw() { testShaderBuild(deferred_light_vert, directional_light_frag); testShaderBuild(deferred_light_vert, directional_ambient_light_frag); testShaderBuild(deferred_light_vert, directional_skybox_light_frag); - testShaderBuild(deferred_light_limited_vert, point_light_frag); - testShaderBuild(deferred_light_limited_vert, spot_light_frag); + testShaderBuild(deferred_light_point_vert, point_light_frag); + testShaderBuild(deferred_light_spot_vert, spot_light_frag); testShaderBuild(standardTransformPNTC_vert, standardDrawTexture_frag); testShaderBuild(standardTransformPNTC_vert, DrawTextureOpaque_frag); From 6a08c74463a94cc3658c5e822317c43c322c3aa4 Mon Sep 17 00:00:00 2001 From: samcake Date: Wed, 7 Sep 2016 18:39:07 -0700 Subject: [PATCH 20/75] Several experimetations without success --- libraries/audio/src/AudioInjector.cpp | 2 +- .../gpu-gl/src/gpu/gl/GLBackendState.cpp | 6 +- .../src/DeferredLightingEffect.cpp | 81 +++++++++++++------ libraries/render-utils/src/LightingModel.h | 3 +- .../render-utils/src/RenderDeferredTask.cpp | 2 +- .../render-utils/src/deferred_light_point.slv | 8 +- .../render-utils/src/deferred_light_spot.slv | 7 +- 7 files changed, 68 insertions(+), 41 deletions(-) diff --git a/libraries/audio/src/AudioInjector.cpp b/libraries/audio/src/AudioInjector.cpp index c6368259c0..5fc07adb8d 100644 --- a/libraries/audio/src/AudioInjector.cpp +++ b/libraries/audio/src/AudioInjector.cpp @@ -26,7 +26,7 @@ #include "SoundCache.h" #include "AudioSRC.h" -int audioInjectorPtrMetaTypeId = qRegisterMetaType(); +//int audioInjectorPtrMetaTypeId = qRegisterMetaType(); AudioInjectorState operator& (AudioInjectorState lhs, AudioInjectorState rhs) { return static_cast(static_cast(lhs) & static_cast(rhs)); diff --git a/libraries/gpu-gl/src/gpu/gl/GLBackendState.cpp b/libraries/gpu-gl/src/gpu/gl/GLBackendState.cpp index f41570ef7b..1b40af6174 100644 --- a/libraries/gpu-gl/src/gpu/gl/GLBackendState.cpp +++ b/libraries/gpu-gl/src/gpu/gl/GLBackendState.cpp @@ -213,13 +213,13 @@ void GLBackend::do_setStateStencil(State::StencilActivation activation, State::S GL_DECR }; if (testFront != testBack) { - glStencilOpSeparate(GL_FRONT, STENCIL_OPS[testFront.getFailOp()], STENCIL_OPS[testFront.getPassOp()], STENCIL_OPS[testFront.getDepthFailOp()]); + glStencilOpSeparate(GL_FRONT, STENCIL_OPS[testFront.getFailOp()], STENCIL_OPS[testFront.getDepthFailOp()], STENCIL_OPS[testFront.getPassOp()]); glStencilFuncSeparate(GL_FRONT, COMPARISON_TO_GL[testFront.getFunction()], testFront.getReference(), testFront.getReadMask()); - glStencilOpSeparate(GL_BACK, STENCIL_OPS[testBack.getFailOp()], STENCIL_OPS[testBack.getPassOp()], STENCIL_OPS[testBack.getDepthFailOp()]); + glStencilOpSeparate(GL_BACK, STENCIL_OPS[testBack.getFailOp()], STENCIL_OPS[testBack.getDepthFailOp()], STENCIL_OPS[testBack.getPassOp()]); glStencilFuncSeparate(GL_BACK, COMPARISON_TO_GL[testBack.getFunction()], testBack.getReference(), testBack.getReadMask()); } else { - glStencilOp(STENCIL_OPS[testFront.getFailOp()], STENCIL_OPS[testFront.getPassOp()], STENCIL_OPS[testFront.getDepthFailOp()]); + glStencilOp(STENCIL_OPS[testFront.getFailOp()], STENCIL_OPS[testFront.getDepthFailOp()], STENCIL_OPS[testFront.getPassOp()]); glStencilFunc(COMPARISON_TO_GL[testFront.getFunction()], testFront.getReference(), testFront.getReadMask()); } diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index 4f14b76ac0..3c6608b011 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -78,6 +78,31 @@ enum DeferredShader_BufferSlot { static void loadLightProgram(const char* vertSource, const char* fragSource, bool lightVolume, gpu::PipelinePointer& program, LightLocationsPtr& locations); static void loadLightVolumeProgram(const char* vertSource, const char* fragSource, bool front, gpu::PipelinePointer& program, LightLocationsPtr& locations); +const char no_light_frag[] = +R"SCRIBE( +//PC 410 core +// Generated on Wed Sep 07 12:11:58 2016 +// +// point_light.frag +// fragment shader +// +// Created by Sam Gateau on 9/18/15. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +out vec4 _fragColor; + +void main(void) { + _fragColor = vec4(1.0, 1.0, 1.0, 1.0); + + } + + +)SCRIBE" +; + void DeferredLightingEffect::init() { _directionalLightLocations = std::make_shared(); _directionalAmbientSphereLightLocations = std::make_shared(); @@ -99,12 +124,12 @@ void DeferredLightingEffect::init() { loadLightProgram(deferred_light_vert, directional_ambient_light_shadow_frag, false, _directionalAmbientSphereLightShadow, _directionalAmbientSphereLightShadowLocations); loadLightProgram(deferred_light_vert, directional_skybox_light_shadow_frag, false, _directionalSkyboxLightShadow, _directionalSkyboxLightShadowLocations); - loadLightProgram(deferred_light_vert, local_lights_shading_frag, false, _localLight, _localLightLocations); + loadLightProgram(deferred_light_vert, local_lights_shading_frag, true, _localLight, _localLightLocations); - loadLightVolumeProgram(deferred_light_point_vert, point_light_frag, false, _pointLightBack, _pointLightLocations); - loadLightVolumeProgram(deferred_light_point_vert, point_light_frag, true, _pointLightFront, _pointLightLocations); - loadLightVolumeProgram(deferred_light_spot_vert, spot_light_frag, false, _spotLightBack, _spotLightLocations); - loadLightVolumeProgram(deferred_light_spot_vert, spot_light_frag, true, _spotLightFront, _spotLightLocations); + loadLightVolumeProgram(deferred_light_point_vert, no_light_frag, false, _pointLightBack, _pointLightLocations); + loadLightVolumeProgram(deferred_light_point_vert, no_light_frag, true, _pointLightFront, _pointLightLocations); + loadLightVolumeProgram(deferred_light_spot_vert, no_light_frag, false, _spotLightBack, _spotLightLocations); + loadLightVolumeProgram(deferred_light_spot_vert, no_light_frag, true, _spotLightFront, _spotLightLocations); // Allocate a global light representing the Global Directional light casting shadow (the sun) and the ambient light _allocatedLights.push_back(std::make_shared()); @@ -223,12 +248,14 @@ static void loadLightProgram(const char* vertSource, const char* fragSource, boo auto state = std::make_shared(); state->setColorWriteMask(true, true, true, false); - // Stencil test all the light passes for objects pixels only, not the background - state->setStencilTest(true, 0xFF, gpu::State::StencilTest(0, 0xFF, gpu::NOT_EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP)); + // state->setStencilTest(true, 0xFF, gpu::State::StencilTest(0, 0xFF, gpu::ALWAYS, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP)); if (lightVolume) { - state->setCullMode(gpu::State::CULL_FRONT); - state->setDepthTest(true, false, gpu::GREATER_EQUAL); + state->setStencilTest(true, 0x00, gpu::State::StencilTest(1, 0xFF, gpu::GREATER_EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP)); + + state->setCullMode(gpu::State::CULL_BACK); + // state->setCullMode(gpu::State::CULL_FRONT); + // state->setDepthTest(true, false, gpu::GREATER_EQUAL); //state->setDepthClampEnable(true); // TODO: We should use DepthClamp and avoid changing geometry for inside /outside cases @@ -236,6 +263,9 @@ static void loadLightProgram(const char* vertSource, const char* fragSource, boo state->setBlendFunction(true, gpu::State::ONE, gpu::State::BLEND_OP_ADD, gpu::State::ONE); } else { + // Stencil test all the light passes for objects pixels only, not the background + state->setStencilTest(true, 0x00, gpu::State::StencilTest(0, 0x01, gpu::NOT_EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP)); + state->setCullMode(gpu::State::CULL_BACK); // additive blending state->setBlendFunction(true, gpu::State::ONE, gpu::State::BLEND_OP_ADD, gpu::State::ONE); @@ -289,25 +319,25 @@ static void loadLightVolumeProgram(const char* vertSource, const char* fragSourc locations->shadowTransformBuffer = program->getBuffers().findLocation("shadowTransformBuffer"); auto state = std::make_shared(); - state->setColorWriteMask(true, true, true, false); - // state->setColorWriteMask(false, false, false, false); + // state->setColorWriteMask(true, true, true, false); + state->setColorWriteMask(false, false, false, false); // Stencil test all the light passes for objects pixels only, not the background if (front) { - state->setCullMode(gpu::State::CULL_FRONT); + state->setCullMode(gpu::State::CULL_BACK); state->setDepthTest(true, false, gpu::LESS_EQUAL); - state->setStencilTest(true, 0xFF, gpu::State::StencilTest(0, 0xFF, gpu::ALWAYS, gpu::State::STENCIL_OP_INCR, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_INCR)); + state->setStencilTest(true, 0xFF, gpu::State::StencilTest(0, 0xFF, gpu::NOT_EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_DECR)); - //state->setDepthClampEnable(true); + // state->setDepthClampEnable(true); // TODO: We should use DepthClamp and avoid changing geometry for inside /outside cases // additive blending // state->setBlendFunction(true, gpu::State::ONE, gpu::State::BLEND_OP_ADD, gpu::State::ONE); } else { - state->setCullMode(gpu::State::CULL_BACK); - state->setDepthTest(true, false, gpu::GREATER_EQUAL); - state->setStencilTest(true, 0xFF, gpu::State::StencilTest(0, 0xFF, gpu::ALWAYS, gpu::State::STENCIL_OP_INCR, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_INCR)); + state->setCullMode(gpu::State::CULL_FRONT); + state->setDepthTest(true, false, gpu::LESS_EQUAL); + state->setStencilTest(true, 0xFF, gpu::State::StencilTest(0, 0xFF, gpu::NOT_EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_INCR)); // additive blending // state->setBlendFunction(true, gpu::State::ONE, gpu::State::BLEND_OP_ADD, gpu::State::ONE); } @@ -690,6 +720,9 @@ void RenderDeferredLocals::run(const render::SceneContextPointer& sceneContext, auto textureFrameTransform = gpu::Framebuffer::evalSubregionTexcoordTransformCoefficients(deferredFramebuffer->getFrameSize(), viewport); + batch.setProjectionTransform(projMat); + batch.setViewTransform(viewTransform, true); + // gather lights auto& srcPointLights = deferredLightingEffect->_pointLights; auto& srcSpotLights = deferredLightingEffect->_spotLights; @@ -720,8 +753,8 @@ void RenderDeferredLocals::run(const render::SceneContextPointer& sceneContext, // before we get to the real lighting, let s try to cull down the number of pixels - { - /* if (numPointLights > 0) { + if (false) { + if (numPointLights > 0) { auto mesh = deferredLightingEffect->getPointLightMesh(); batch.setIndexBuffer(mesh->getIndexBuffer()); batch.setInputBuffer(0, mesh->getVertexBuffer()); @@ -730,16 +763,14 @@ void RenderDeferredLocals::run(const render::SceneContextPointer& sceneContext, // Point light pipeline batch.setPipeline(deferredLightingEffect->_pointLightBack); - batch._glUniform4fv(deferredLightingEffect->_pointLightLocations->texcoordFrameTransform, 1, reinterpret_cast(&textureFrameTransform)); batch.drawIndexedInstanced(numPointLights, model::Mesh::topologyToPrimitive(pointPart._topology), pointPart._numIndices, pointPart._startIndex, offsetPointLights); batch.setPipeline(deferredLightingEffect->_pointLightFront); - batch._glUniform4fv(deferredLightingEffect->_pointLightLocations->texcoordFrameTransform, 1, reinterpret_cast(&textureFrameTransform)); batch.drawIndexedInstanced(numPointLights, model::Mesh::topologyToPrimitive(pointPart._topology), pointPart._numIndices, pointPart._startIndex, offsetPointLights); - } */ - /* + } + if (numSpotLights > 0) { auto mesh = deferredLightingEffect->getSpotLightMesh(); batch.setIndexBuffer(mesh->getIndexBuffer()); @@ -749,15 +780,13 @@ void RenderDeferredLocals::run(const render::SceneContextPointer& sceneContext, // Spot light pipeline batch.setPipeline(deferredLightingEffect->_spotLightBack); - batch._glUniform4fv(deferredLightingEffect->_spotLightLocations->texcoordFrameTransform, 1, reinterpret_cast(&textureFrameTransform)); batch.drawIndexedInstanced(numSpotLights, model::Mesh::topologyToPrimitive(conePart._topology), conePart._numIndices, conePart._startIndex, offsetSpotLights); batch.setPipeline(deferredLightingEffect->_spotLightFront); - batch._glUniform4fv(deferredLightingEffect->_spotLightLocations->texcoordFrameTransform, 1, reinterpret_cast(&textureFrameTransform)); batch.drawIndexedInstanced(numSpotLights, model::Mesh::topologyToPrimitive(conePart._topology), conePart._numIndices, conePart._startIndex, offsetSpotLights); - }*/ + } } // Local light pipeline diff --git a/libraries/render-utils/src/LightingModel.h b/libraries/render-utils/src/LightingModel.h index 87a6703dc6..5bb0e621a4 100644 --- a/libraries/render-utils/src/LightingModel.h +++ b/libraries/render-utils/src/LightingModel.h @@ -143,7 +143,8 @@ public: bool enablePointLight{ true }; bool enableSpotLight{ true }; - bool showLightContour{ false }; // false by default + // bool showLightContour { false }; // false by default + bool showLightContour { true }; // false by default signals: void dirty(); diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 32aa2b6e16..942419a8a4 100755 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -390,7 +390,7 @@ gpu::PipelinePointer DrawStencilDeferred::getOpaquePipeline() { auto state = std::make_shared(); state->setDepthTest(true, false, gpu::LESS_EQUAL); - state->setStencilTest(true, 0xFF, gpu::State::StencilTest(STENCIL_OPAQUE, 0xFF, gpu::ALWAYS, gpu::State::STENCIL_OP_REPLACE, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_REPLACE)); + state->setStencilTest(true, 0xFF, gpu::State::StencilTest(STENCIL_OPAQUE, 0xFF, gpu::ALWAYS, gpu::State::STENCIL_OP_REPLACE, gpu::State::STENCIL_OP_REPLACE, gpu::State::STENCIL_OP_KEEP)); state->setColorWriteMask(0); _opaquePipeline = gpu::Pipeline::create(program, state); diff --git a/libraries/render-utils/src/deferred_light_point.slv b/libraries/render-utils/src/deferred_light_point.slv index f6d4de3954..6bdc6fe42f 100644 --- a/libraries/render-utils/src/deferred_light_point.slv +++ b/libraries/render-utils/src/deferred_light_point.slv @@ -30,17 +30,19 @@ out vec4 _texCoord0; void main(void) { - instanceID = lightIndex[gl_InstanceID]; + int instanceID = lightIndex[gl_InstanceID]; Light light = getLight(instanceID); vec4 sphereVertex = inPosition; + vec3 lightOrigin = getLightPosition(light); vec4 sphereParam = getLightVolumeGeometry(light); sphereVertex.xyz *= sphereParam.w; + sphereVertex.xyz += lightOrigin; + // standard transform TransformCamera cam = getTransformCamera(); - TransformObject obj = getTransformObject(); - <$transformModelToClipPos(cam, obj, sphereVertex, gl_Position)$>; + <$transformWorldToClipPos(cam, sphereVertex, gl_Position)$>; vec4 projected = gl_Position / gl_Position.w; projected.xy = (projected.xy + 1.0) * 0.5; diff --git a/libraries/render-utils/src/deferred_light_spot.slv b/libraries/render-utils/src/deferred_light_spot.slv index cd70724e1f..c120fa28b1 100755 --- a/libraries/render-utils/src/deferred_light_spot.slv +++ b/libraries/render-utils/src/deferred_light_spot.slv @@ -25,11 +25,10 @@ uniform lightIndexBuffer { int lightIndex[120]; }; out vec4 _texCoord0; -flat out int instanceID; void main(void) { vec4 coneVertex = inPosition; - instanceID = lightIndex[gl_InstanceID]; + int instanceID = lightIndex[gl_InstanceID]; Light light = getLight(instanceID); vec3 lightPos = getLightPosition(light); vec4 coneParam = getLightVolumeGeometry(light); @@ -53,10 +52,6 @@ void main(void) { // standard transform TransformCamera cam = getTransformCamera(); - - ; !> - <$transformWorldToClipPos(cam, coneVertex, gl_Position)$>; vec4 projected = gl_Position / gl_Position.w; From a4df8a84b7c26ef5a0ddba3a55741cb44dc8be9d Mon Sep 17 00:00:00 2001 From: sam Date: Thu, 8 Sep 2016 00:11:54 -0700 Subject: [PATCH 21/75] introducing the light Clusters --- .../src/DeferredLightingEffect.cpp | 69 +++---------------- libraries/render-utils/src/LightClusters.cpp | 12 ++++ libraries/render-utils/src/LightClusters.h | 28 ++++++++ 3 files changed, 50 insertions(+), 59 deletions(-) create mode 100644 libraries/render-utils/src/LightClusters.cpp create mode 100644 libraries/render-utils/src/LightClusters.h diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index 3c6608b011..94c12f7d99 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -80,26 +80,11 @@ static void loadLightVolumeProgram(const char* vertSource, const char* fragSourc const char no_light_frag[] = R"SCRIBE( -//PC 410 core -// Generated on Wed Sep 07 12:11:58 2016 -// -// point_light.frag -// fragment shader -// -// Created by Sam Gateau on 9/18/15. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// out vec4 _fragColor; void main(void) { _fragColor = vec4(1.0, 1.0, 1.0, 1.0); - - } - - +} )SCRIBE" ; @@ -201,8 +186,7 @@ void DeferredLightingEffect::setupKeyLightBatch(gpu::Batch& batch, int lightBuff batch.setResourceTexture(skyboxCubemapUnit, keyLight->getAmbientMap()); } } - -static void loadLightProgram(const char* vertSource, const char* fragSource, bool lightVolume, gpu::PipelinePointer& pipeline, LightLocationsPtr& locations) { +static gpu::ShaderPointer makeLightProgram(const char* vertSource, const char* fragSource, LightLocationsPtr& locations) { auto VS = gpu::Shader::createVertex(std::string(vertSource)); auto PS = gpu::Shader::createPixel(std::string(fragSource)); @@ -245,6 +229,13 @@ static void loadLightProgram(const char* vertSource, const char* fragSource, boo locations->subsurfaceScatteringParametersBuffer = program->getBuffers().findLocation("subsurfaceScatteringParametersBuffer"); locations->shadowTransformBuffer = program->getBuffers().findLocation("shadowTransformBuffer"); + return program; +} + +static void loadLightProgram(const char* vertSource, const char* fragSource, bool lightVolume, gpu::PipelinePointer& pipeline, LightLocationsPtr& locations) { + + gpu::ShaderPointer program = makeLightProgram(vertSource, fragSource, locations); + auto state = std::make_shared(); state->setColorWriteMask(true, true, true, false); @@ -276,47 +267,7 @@ static void loadLightProgram(const char* vertSource, const char* fragSource, boo static void loadLightVolumeProgram(const char* vertSource, const char* fragSource, bool front, gpu::PipelinePointer& pipeline, LightLocationsPtr& locations) { - auto VS = gpu::Shader::createVertex(std::string(vertSource)); - auto PS = gpu::Shader::createPixel(std::string(fragSource)); - - gpu::ShaderPointer program = gpu::Shader::createProgram(VS, PS); - - gpu::Shader::BindingSet slotBindings; - slotBindings.insert(gpu::Shader::Binding(std::string("colorMap"), DEFERRED_BUFFER_COLOR_UNIT)); - slotBindings.insert(gpu::Shader::Binding(std::string("normalMap"), DEFERRED_BUFFER_NORMAL_UNIT)); - slotBindings.insert(gpu::Shader::Binding(std::string("specularMap"), DEFERRED_BUFFER_EMISSIVE_UNIT)); - slotBindings.insert(gpu::Shader::Binding(std::string("depthMap"), DEFERRED_BUFFER_DEPTH_UNIT)); - slotBindings.insert(gpu::Shader::Binding(std::string("obscuranceMap"), DEFERRED_BUFFER_OBSCURANCE_UNIT)); - slotBindings.insert(gpu::Shader::Binding(std::string("shadowMap"), SHADOW_MAP_UNIT)); - slotBindings.insert(gpu::Shader::Binding(std::string("skyboxMap"), SKYBOX_MAP_UNIT)); - - slotBindings.insert(gpu::Shader::Binding(std::string("linearZeyeMap"), DEFERRED_BUFFER_LINEAR_DEPTH_UNIT)); - slotBindings.insert(gpu::Shader::Binding(std::string("curvatureMap"), DEFERRED_BUFFER_CURVATURE_UNIT)); - slotBindings.insert(gpu::Shader::Binding(std::string("diffusedCurvatureMap"), DEFERRED_BUFFER_DIFFUSED_CURVATURE_UNIT)); - slotBindings.insert(gpu::Shader::Binding(std::string("scatteringLUT"), SCATTERING_LUT_UNIT)); - slotBindings.insert(gpu::Shader::Binding(std::string("scatteringSpecularBeckmann"), SCATTERING_SPECULAR_UNIT)); - - - slotBindings.insert(gpu::Shader::Binding(std::string("cameraCorrectionBuffer"), CAMERA_CORRECTION_BUFFER_SLOT)); - slotBindings.insert(gpu::Shader::Binding(std::string("deferredFrameTransformBuffer"), DEFERRED_FRAME_TRANSFORM_BUFFER_SLOT)); - slotBindings.insert(gpu::Shader::Binding(std::string("lightingModelBuffer"), LIGHTING_MODEL_BUFFER_SLOT)); - slotBindings.insert(gpu::Shader::Binding(std::string("subsurfaceScatteringParametersBuffer"), SCATTERING_PARAMETERS_BUFFER_SLOT)); - slotBindings.insert(gpu::Shader::Binding(std::string("lightBuffer"), LIGHT_GPU_SLOT)); - slotBindings.insert(gpu::Shader::Binding(std::string("lightIndexBuffer"), LIGHT_INDEX_GPU_SLOT)); - - - gpu::Shader::makeProgram(*program, slotBindings); - - locations->radius = program->getUniforms().findLocation("radius"); - locations->ambientSphere = program->getUniforms().findLocation("ambientSphere.L00"); - - locations->texcoordFrameTransform = program->getUniforms().findLocation("texcoordFrameTransform"); - - locations->lightBufferUnit = program->getBuffers().findLocation("lightBuffer"); - locations->lightIndexBufferUnit = program->getBuffers().findLocation("lightIndexBuffer"); - locations->deferredFrameTransformBuffer = program->getBuffers().findLocation("deferredFrameTransformBuffer"); - locations->subsurfaceScatteringParametersBuffer = program->getBuffers().findLocation("subsurfaceScatteringParametersBuffer"); - locations->shadowTransformBuffer = program->getBuffers().findLocation("shadowTransformBuffer"); + gpu::ShaderPointer program = makeLightProgram(vertSource, fragSource, locations); auto state = std::make_shared(); // state->setColorWriteMask(true, true, true, false); diff --git a/libraries/render-utils/src/LightClusters.cpp b/libraries/render-utils/src/LightClusters.cpp new file mode 100644 index 0000000000..f266be988a --- /dev/null +++ b/libraries/render-utils/src/LightClusters.cpp @@ -0,0 +1,12 @@ +// +// LightClusters.cpp +// +// Created by Sam Gateau on 9/7/2016. +// Copyright 2015 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 "LightClusters.h" + diff --git a/libraries/render-utils/src/LightClusters.h b/libraries/render-utils/src/LightClusters.h new file mode 100644 index 0000000000..3557ec0ed0 --- /dev/null +++ b/libraries/render-utils/src/LightClusters.h @@ -0,0 +1,28 @@ +// +// LightClusters.h +// +// Created by Sam Gateau on 9/7/2016. +// Copyright 2015 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_utils_LightClusters_h +#define hifi_render_utils_LightClusters_h + +#include "gpu/Framebuffer.h" + +#include "LightStage.h" + +class ViewFrustum; + +class LightClusters { +public: + + LightStagePointer _lightStage; + + gpu::BufferPointer _lightIndicesBuffer; +}; + +#endif From 25616be7c1b51858fbb5d9ead6603a8debc15682 Mon Sep 17 00:00:00 2001 From: sam Date: Thu, 8 Sep 2016 02:16:13 -0700 Subject: [PATCH 22/75] introducing the light Clusters --- libraries/render-utils/src/LightClusters.h | 52 +++++++++++++++++++++- libraries/render-utils/src/LightStage.h | 2 +- 2 files changed, 52 insertions(+), 2 deletions(-) diff --git a/libraries/render-utils/src/LightClusters.h b/libraries/render-utils/src/LightClusters.h index 3557ec0ed0..b3a2271b2e 100644 --- a/libraries/render-utils/src/LightClusters.h +++ b/libraries/render-utils/src/LightClusters.h @@ -15,11 +15,61 @@ #include "LightStage.h" -class ViewFrustum; +#include +/* +class FrustumGrid { +public: + float _near { 0.1f }; + float _nearPrime { 1.0f }; + float _farPrime { 400.0f }; + float _far { 10000.0f }; + glm::uvec3 _dims { 16, 16, 16 }; + + float viewToLinearDepth(float depth) const { + float nDepth = -depth; + float ldepth = (nDepth - _nearPrime) / (_farPrime - _nearPrime); + + if (ldepth < 0.0f) { + return (nDepth - _near) / (_nearPrime - _near) - 1.0f; + } + if (ldepth > 1.0f) { + return (nDepth - _farPrime) / (_far - _farPrime) + 1.0f; + } + return ldepth; + } + + float linearToGridDepth(float depth) const { + return depth / (float) _dims.z; + } + + glm::vec2 linearToGridXY(const glm::vec3& cpos) const { + return glm::vec2(cpos.x / (float) _dims.x, cpos.y / (float) _dims.y); + } + + int gridDepthToLayer(float gridDepth) const { + return (int) gridDepth; + } + + glm::ivec3 viewToGridPos(const glm::vec3& pos) const { + + return glm::ivec3(0); + } + +}; +*/ class LightClusters { public: + LightClusters(); + + + void updateFrustum(const ViewFrustum& frustum); + + + + ViewFrustum _frustum; + LightStagePointer _lightStage; gpu::BufferPointer _lightIndicesBuffer; diff --git a/libraries/render-utils/src/LightStage.h b/libraries/render-utils/src/LightStage.h index 4319eb80ba..b0d5c1749f 100644 --- a/libraries/render-utils/src/LightStage.h +++ b/libraries/render-utils/src/LightStage.h @@ -110,5 +110,5 @@ public: Shadows _shadows; }; - +using LightStagePointer = std::shared_ptr; #endif From 61de063b29ebc0f93ee88a3a245dbe2cce45b8a7 Mon Sep 17 00:00:00 2001 From: samcake Date: Thu, 8 Sep 2016 18:02:35 -0700 Subject: [PATCH 23/75] Developping the Light Clusters, adding visualization --- libraries/gpu/src/gpu/Buffer.h | 17 +++ .../src/AmbientOcclusionEffect.cpp | 30 ++--- .../render-utils/src/AmbientOcclusionEffect.h | 24 +--- .../src/DeferredLightingEffect.cpp | 40 +++++-- .../render-utils/src/DeferredLightingEffect.h | 11 +- libraries/render-utils/src/LightClusters.cpp | 111 ++++++++++++++++++ libraries/render-utils/src/LightClusters.h | 98 ++++++++++++++-- libraries/render-utils/src/LightStage.h | 2 + .../render-utils/src/RenderDeferredTask.cpp | 5 + .../render-utils/src/RenderShadowTask.cpp | 10 +- .../render-utils/src/SubsurfaceScattering.cpp | 2 +- .../src/lightClusters_drawGrid.slf | 19 +++ .../src/lightClusters_drawGrid.slv | 89 ++++++++++++++ libraries/shared/src/ViewFrustum.cpp | 20 ++++ libraries/shared/src/ViewFrustum.h | 3 + 15 files changed, 412 insertions(+), 69 deletions(-) create mode 100644 libraries/render-utils/src/lightClusters_drawGrid.slf create mode 100644 libraries/render-utils/src/lightClusters_drawGrid.slv diff --git a/libraries/gpu/src/gpu/Buffer.h b/libraries/gpu/src/gpu/Buffer.h index 3233dad8a9..e8e04f471a 100644 --- a/libraries/gpu/src/gpu/Buffer.h +++ b/libraries/gpu/src/gpu/Buffer.h @@ -380,6 +380,23 @@ public: } }; + + template class StructBuffer : public gpu::BufferView { + public: + + static BufferPointer makeBuffer() { + T t; + return std::make_shared(sizeof(T), (const gpu::Byte*) &t); + } + ~StructBuffer() {}; + StructBuffer() : gpu::BufferView(makeBuffer()) {} + + const T* operator ->() const { return &get(); } + T& edit() { + return BufferView::edit(0); + } + + }; }; #endif diff --git a/libraries/render-utils/src/AmbientOcclusionEffect.cpp b/libraries/render-utils/src/AmbientOcclusionEffect.cpp index 61a8c1f994..4d8403fc4d 100644 --- a/libraries/render-utils/src/AmbientOcclusionEffect.cpp +++ b/libraries/render-utils/src/AmbientOcclusionEffect.cpp @@ -184,46 +184,46 @@ void AmbientOcclusionEffect::configure(const Config& config) { const double RADIUS_POWER = 6.0; const auto& radius = config.radius; if (radius != _parametersBuffer->getRadius()) { - auto& current = _parametersBuffer->radiusInfo; + auto& current = _parametersBuffer.edit().radiusInfo; current.x = radius; current.y = radius * radius; current.z = (float)(1.0 / pow((double)radius, RADIUS_POWER)); } if (config.obscuranceLevel != _parametersBuffer->getObscuranceLevel()) { - auto& current = _parametersBuffer->radiusInfo; + auto& current = _parametersBuffer.edit().radiusInfo; current.w = config.obscuranceLevel; } if (config.falloffBias != _parametersBuffer->getFalloffBias()) { - auto& current = _parametersBuffer->ditheringInfo; + auto& current = _parametersBuffer.edit().ditheringInfo; current.z = config.falloffBias; } if (config.edgeSharpness != _parametersBuffer->getEdgeSharpness()) { - auto& current = _parametersBuffer->blurInfo; + auto& current = _parametersBuffer.edit().blurInfo; current.x = config.edgeSharpness; } if (config.blurDeviation != _parametersBuffer->getBlurDeviation()) { - auto& current = _parametersBuffer->blurInfo; + auto& current = _parametersBuffer.edit().blurInfo; current.z = config.blurDeviation; shouldUpdateGaussian = true; } if (config.numSpiralTurns != _parametersBuffer->getNumSpiralTurns()) { - auto& current = _parametersBuffer->sampleInfo; + auto& current = _parametersBuffer.edit().sampleInfo; current.z = config.numSpiralTurns; } if (config.numSamples != _parametersBuffer->getNumSamples()) { - auto& current = _parametersBuffer->sampleInfo; + auto& current = _parametersBuffer.edit().sampleInfo; current.x = config.numSamples; current.y = 1.0f / config.numSamples; } if (config.fetchMipsEnabled != _parametersBuffer->isFetchMipsEnabled()) { - auto& current = _parametersBuffer->sampleInfo; + auto& current = _parametersBuffer.edit().sampleInfo; current.w = (float)config.fetchMipsEnabled; } @@ -232,26 +232,26 @@ void AmbientOcclusionEffect::configure(const Config& config) { } if (config.perspectiveScale != _parametersBuffer->getPerspectiveScale()) { - _parametersBuffer->resolutionInfo.z = config.perspectiveScale; + _parametersBuffer.edit().resolutionInfo.z = config.perspectiveScale; } if (config.resolutionLevel != _parametersBuffer->getResolutionLevel()) { - auto& current = _parametersBuffer->resolutionInfo; + auto& current = _parametersBuffer.edit().resolutionInfo; current.x = (float) config.resolutionLevel; } if (config.blurRadius != _parametersBuffer->getBlurRadius()) { - auto& current = _parametersBuffer->blurInfo; + auto& current = _parametersBuffer.edit().blurInfo; current.y = (float)config.blurRadius; shouldUpdateGaussian = true; } if (config.ditheringEnabled != _parametersBuffer->isDitheringEnabled()) { - auto& current = _parametersBuffer->ditheringInfo; + auto& current = _parametersBuffer.edit().ditheringInfo; current.x = (float)config.ditheringEnabled; } if (config.borderingEnabled != _parametersBuffer->isBorderingEnabled()) { - auto& current = _parametersBuffer->ditheringInfo; + auto& current = _parametersBuffer.edit().ditheringInfo; current.w = (float)config.borderingEnabled; } @@ -334,7 +334,7 @@ const gpu::PipelinePointer& AmbientOcclusionEffect::getVBlurPipeline() { } void AmbientOcclusionEffect::updateGaussianDistribution() { - auto coefs = _parametersBuffer->_gaussianCoefs; + auto coefs = _parametersBuffer.edit()._gaussianCoefs; GaussianDistribution::evalSampling(coefs, Parameters::GAUSSIAN_COEFS_LENGTH, _parametersBuffer->getBlurRadius(), _parametersBuffer->getBlurDeviation()); } @@ -451,7 +451,7 @@ void DebugAmbientOcclusion::configure(const Config& config) { auto cursorPos = glm::vec2(_parametersBuffer->pixelInfo); if (cursorPos != config.debugCursorTexcoord) { - _parametersBuffer->pixelInfo = glm::vec4(config.debugCursorTexcoord, 0.0f, 0.0f); + _parametersBuffer.edit().pixelInfo = glm::vec4(config.debugCursorTexcoord, 0.0f, 0.0f); } } diff --git a/libraries/render-utils/src/AmbientOcclusionEffect.h b/libraries/render-utils/src/AmbientOcclusionEffect.h index 80904c80a3..4e41926f9f 100644 --- a/libraries/render-utils/src/AmbientOcclusionEffect.h +++ b/libraries/render-utils/src/AmbientOcclusionEffect.h @@ -104,26 +104,6 @@ signals: void dirty(); }; - -namespace gpu { -template class UniformBuffer : public gpu::BufferView { - public: - - static BufferPointer makeBuffer() { - T t; - return std::make_shared(sizeof(T), (const gpu::Byte*) &t); - } - ~UniformBuffer() {}; - UniformBuffer() : gpu::BufferView(makeBuffer()) {} - - const T* operator ->() const { return &get(); } - T* operator ->() { - return &edit(0); - } - -}; -} - class AmbientOcclusionEffect { public: using Inputs = render::VaryingSet3; @@ -172,7 +152,7 @@ public: bool isDitheringEnabled() const { return ditheringInfo.x; } bool isBorderingEnabled() const { return ditheringInfo.w; } }; - using ParametersBuffer = gpu::UniformBuffer; + using ParametersBuffer = gpu::StructBuffer; private: void updateGaussianDistribution(); @@ -232,7 +212,7 @@ private: Parameters() {} }; - gpu::UniformBuffer _parametersBuffer; + gpu::StructBuffer _parametersBuffer; const gpu::PipelinePointer& getDebugPipeline(); diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index 94c12f7d99..7c81aeea22 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -116,6 +116,11 @@ void DeferredLightingEffect::init() { loadLightVolumeProgram(deferred_light_spot_vert, no_light_frag, false, _spotLightBack, _spotLightLocations); loadLightVolumeProgram(deferred_light_spot_vert, no_light_frag, true, _spotLightFront, _spotLightLocations); + // Light Stage and clusters + _lightStage = std::make_shared(); + _lightClusters = std::make_shared(); + _lightClusters->updateLightStage(_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::LightPointer lp = _allocatedLights[0]; @@ -127,13 +132,13 @@ void DeferredLightingEffect::init() { 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)); + _globalLights.push_back(_lightStage->addLight(lp)); } void DeferredLightingEffect::addLight(const model::LightPointer& light) { assert(light); - auto lightID = _lightStage.addLight(light); + auto lightID = _lightStage->addLight(light); if (light->getType() == model::Light::POINT) { _pointLights.push_back(lightID); } else { @@ -239,10 +244,8 @@ static void loadLightProgram(const char* vertSource, const char* fragSource, boo auto state = std::make_shared(); state->setColorWriteMask(true, true, true, false); - // state->setStencilTest(true, 0xFF, gpu::State::StencilTest(0, 0xFF, gpu::ALWAYS, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP)); - if (lightVolume) { - state->setStencilTest(true, 0x00, gpu::State::StencilTest(1, 0xFF, gpu::GREATER_EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP)); + state->setStencilTest(true, 0x00, gpu::State::StencilTest(1, 0xFF, gpu::LESS_EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP)); state->setCullMode(gpu::State::CULL_BACK); // state->setCullMode(gpu::State::CULL_FRONT); @@ -270,27 +273,29 @@ static void loadLightVolumeProgram(const char* vertSource, const char* fragSourc gpu::ShaderPointer program = makeLightProgram(vertSource, fragSource, locations); auto state = std::make_shared(); - // state->setColorWriteMask(true, true, true, false); - state->setColorWriteMask(false, false, false, false); // Stencil test all the light passes for objects pixels only, not the background if (front) { state->setCullMode(gpu::State::CULL_BACK); state->setDepthTest(true, false, gpu::LESS_EQUAL); - state->setStencilTest(true, 0xFF, gpu::State::StencilTest(0, 0xFF, gpu::NOT_EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_DECR)); + state->setStencilTest(true, 0xFF, gpu::State::StencilTest(0, 0xFF, gpu::NOT_EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_DECR, gpu::State::STENCIL_OP_KEEP)); // state->setDepthClampEnable(true); // TODO: We should use DepthClamp and avoid changing geometry for inside /outside cases // additive blending // state->setBlendFunction(true, gpu::State::ONE, gpu::State::BLEND_OP_ADD, gpu::State::ONE); + //state->setColorWriteMask(true, true, true, false); + state->setColorWriteMask(false, false, false, false); } else { state->setCullMode(gpu::State::CULL_FRONT); state->setDepthTest(true, false, gpu::LESS_EQUAL); - state->setStencilTest(true, 0xFF, gpu::State::StencilTest(0, 0xFF, gpu::NOT_EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_INCR)); + state->setStencilTest(true, 0xFF, gpu::State::StencilTest(0, 0xFF, gpu::NOT_EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_INCR, gpu::State::STENCIL_OP_KEEP)); // additive blending // state->setBlendFunction(true, gpu::State::ONE, gpu::State::BLEND_OP_ADD, gpu::State::ONE); + // state->setColorWriteMask(true, true, true, false); + state->setColorWriteMask(false, false, false, false); } pipeline = gpu::Pipeline::create(program, state); @@ -568,8 +573,8 @@ void RenderDeferredSetup::run(const render::SceneContextPointer& sceneContext, c // Global directional light and ambient pass - assert(deferredLightingEffect->getLightStage().getNumLights() > 0); - auto lightAndShadow = deferredLightingEffect->getLightStage().getLightAndShadow(0); + assert(deferredLightingEffect->getLightStage()->getNumLights() > 0); + auto lightAndShadow = deferredLightingEffect->getLightStage()->getLightAndShadow(0); const auto& globalShadow = lightAndShadow.second; // Bind the shadow buffer @@ -682,6 +687,8 @@ void RenderDeferredLocals::run(const render::SceneContextPointer& sceneContext, int numSpotLights = (int) srcSpotLights.size(); int offsetSpotLights = numPointLights; + auto lightClusters = deferredLightingEffect->_lightClusters; + std::vector lightIndices(numPointLights + numSpotLights + 1); lightIndices[0] = 0; @@ -695,11 +702,20 @@ void RenderDeferredLocals::run(const render::SceneContextPointer& sceneContext, } if (lightIndices[0] > 0) { + static int frame = 0; + frame++; + + if (frame % 1000 == 0) { + lightClusters->updateFrustum(viewFrustum); + + lightClusters->updateVisibleLights(lightIndices); + } _localLightsBuffer._buffer->setData(lightIndices.size() * sizeof(int), (const gpu::Byte*) lightIndices.data()); _localLightsBuffer._size = lightIndices.size() * sizeof(int); + // Bind the global list of lights and the visible lights this frame - batch.setUniformBuffer(deferredLightingEffect->_localLightLocations->lightBufferUnit, deferredLightingEffect->getLightStage()._lightArrayBuffer); + batch.setUniformBuffer(deferredLightingEffect->_localLightLocations->lightBufferUnit, deferredLightingEffect->getLightStage()->_lightArrayBuffer); batch.setUniformBuffer(deferredLightingEffect->_localLightLocations->lightIndexBufferUnit, _localLightsBuffer); diff --git a/libraries/render-utils/src/DeferredLightingEffect.h b/libraries/render-utils/src/DeferredLightingEffect.h index cbf5ff6ab3..ce29480950 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.h +++ b/libraries/render-utils/src/DeferredLightingEffect.h @@ -28,6 +28,8 @@ #include "LightingModel.h" #include "LightStage.h" +#include "LightClusters.h" + #include "SurfaceGeometryPass.h" #include "SubsurfaceScattering.h" #include "AmbientOcclusionEffect.h" @@ -59,7 +61,8 @@ public: // update global lighting void setGlobalLight(const model::LightPointer& light); - const LightStage& getLightStage() { return _lightStage; } + const LightStagePointer getLightStage() { return _lightStage; } + const LightClustersPointer getLightClusters() { return _lightClusters; } void setShadowMapEnabled(bool enable) { _shadowMapEnabled = enable; }; void setAmbientOcclusionEnabled(bool enable) { _ambientOcclusionEnabled = enable; } @@ -68,7 +71,9 @@ public: private: DeferredLightingEffect() = default; - LightStage _lightStage; + LightStagePointer _lightStage; + + LightClustersPointer _lightClusters; bool _shadowMapEnabled{ false }; bool _ambientOcclusionEnabled{ false }; @@ -200,4 +205,6 @@ protected: gpu::RangeTimerPointer _gpuTimer; }; + + #endif // hifi_DeferredLightingEffect_h diff --git a/libraries/render-utils/src/LightClusters.cpp b/libraries/render-utils/src/LightClusters.cpp index f266be988a..77fe7fa798 100644 --- a/libraries/render-utils/src/LightClusters.cpp +++ b/libraries/render-utils/src/LightClusters.cpp @@ -10,3 +10,114 @@ #include "LightClusters.h" + +#include +#include "lightClusters_drawGrid_vert.h" +#include "lightClusters_drawGrid_frag.h" + +enum LightClusterGridShader_BufferSlot { + LIGHT_CLUSTER_GRID_FRUSTUM_GRID_SLOT = 0, +}; + +#include "DeferredLightingEffect.h" + +LightClusters::LightClusters() { +} + +void LightClusters::updateFrustum(const ViewFrustum& frustum) { + _frustum = frustum; + + _frustrumGridBuffer.edit().updateFrustrum(frustum); +} + +void LightClusters::updateLightStage(const LightStagePointer& lightStage) { + _lightStage = lightStage; +} + +void LightClusters::updateVisibleLights(const LightStage::LightIndices& visibleLights) { + +} + + + + + +DebugLightClusters::DebugLightClusters() { + +} + + +void DebugLightClusters::configure(const Config& config) { +} + +const gpu::PipelinePointer DebugLightClusters::getDrawClusterGridPipeline() { + if (!_drawClusterGrid) { + auto vs = gpu::Shader::createVertex(std::string(lightClusters_drawGrid_vert)); + auto ps = gpu::Shader::createPixel(std::string(lightClusters_drawGrid_frag)); + gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps); + + gpu::Shader::BindingSet slotBindings; + slotBindings.insert(gpu::Shader::Binding(std::string("frustrumGridBuffer"), LIGHT_CLUSTER_GRID_FRUSTUM_GRID_SLOT)); + + gpu::Shader::makeProgram(*program, slotBindings); + + + auto state = std::make_shared(); + + state->setDepthTest(true, false, gpu::LESS_EQUAL); + + // Blend on transparent + state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA); + + // Good to go add the brand new pipeline + _drawClusterGrid = gpu::Pipeline::create(program, state); + } + return _drawClusterGrid; +} + +void DebugLightClusters::run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext) { + auto deferredLightingEffect = DependencyManager::get(); + auto lightClusters = deferredLightingEffect->getLightClusters(); + + + /* auto deferredTransform = inputs.get0(); + auto deferredFramebuffer = inputs.get1(); + auto lightingModel = inputs.get2(); + auto surfaceGeometryFramebuffer = inputs.get3(); + auto ssaoFramebuffer = inputs.get4(); + auto subsurfaceScatteringResource = inputs.get5(); + */ + auto args = renderContext->args; + + + auto drawPipeline = getDrawClusterGridPipeline(); + + gpu::Batch batch; + + + // Assign the camera transform + batch.setViewportTransform(args->_viewport); + glm::mat4 projMat; + Transform viewMat; + args->getViewFrustum().evalProjectionMatrix(projMat); + args->getViewFrustum().evalViewTransform(viewMat); + batch.setProjectionTransform(projMat); + batch.setViewTransform(viewMat, true); + + + // Then the actual ClusterGrid attributes + batch.setModelTransform(Transform()); + + batch.setUniformBuffer(LIGHT_CLUSTER_GRID_FRUSTUM_GRID_SLOT, lightClusters->_frustrumGridBuffer); + + // bind the one gpu::Pipeline we need + batch.setPipeline(drawPipeline); + + if (true) { + batch.draw(gpu::LINES, 24, 0); + } + + + args->_context->appendFrameBatch(batch); + +} \ No newline at end of file diff --git a/libraries/render-utils/src/LightClusters.h b/libraries/render-utils/src/LightClusters.h index b3a2271b2e..9cec0786ed 100644 --- a/libraries/render-utils/src/LightClusters.h +++ b/libraries/render-utils/src/LightClusters.h @@ -11,12 +11,12 @@ #ifndef hifi_render_utils_LightClusters_h #define hifi_render_utils_LightClusters_h -#include "gpu/Framebuffer.h" - +#include +#include #include "LightStage.h" #include -/* + class FrustumGrid { public: float _near { 0.1f }; @@ -25,6 +25,12 @@ public: float _far { 10000.0f }; glm::uvec3 _dims { 16, 16, 16 }; + float spare; + + glm::mat4 _eyeToGridProj; + glm::mat4 _eyeToGridProjInv; + glm::mat4 _worldToEyeMat; + glm::mat4 _eyeToWorldMat; float viewToLinearDepth(float depth) const { float nDepth = -depth; @@ -43,36 +49,104 @@ public: return depth / (float) _dims.z; } - glm::vec2 linearToGridXY(const glm::vec3& cpos) const { - return glm::vec2(cpos.x / (float) _dims.x, cpos.y / (float) _dims.y); - } - int gridDepthToLayer(float gridDepth) const { return (int) gridDepth; } + glm::vec2 ndcToGridXY(const glm::vec3& ncpos) const { + return 0.5f * glm::vec2((ncpos.x + 1.0f) / (float)_dims.x, (ncpos.y + 1.0f) / (float)_dims.y); + } + glm::ivec3 viewToGridPos(const glm::vec3& pos) const { - - return glm::ivec3(0); + float z = linearToGridDepth(viewToLinearDepth(pos.z)); + + auto cpos = _eyeToGridProj * glm::vec4(pos, 1.0f); + + glm::vec3 ncpos(cpos); + ncpos /= cpos.w; + + + return glm::ivec3(ndcToGridXY(ncpos), (int) linearToGridDepth(z)); + } + + void updateFrustrum(const ViewFrustum& frustum) { + _eyeToGridProj = frustum.evalProjectionMatrixRange(_nearPrime, _farPrime); + _eyeToGridProjInv = glm::inverse(_eyeToGridProj); + + Transform view; + frustum.evalViewTransform(view); + _eyeToWorldMat = view.getMatrix(); + _worldToEyeMat = view.getInverseMatrix(); } }; -*/ + class LightClusters { public: LightClusters(); - void updateFrustum(const ViewFrustum& frustum); - + void updateLightStage(const LightStagePointer& lightStage); + + void updateVisibleLights(const LightStage::LightIndices& visibleLights); + + + // FrustumGrid _grid; ViewFrustum _frustum; LightStagePointer _lightStage; + + + gpu::StructBuffer _frustrumGridBuffer; + + gpu::BufferPointer _lightIndicesBuffer; }; +using LightClustersPointer = std::shared_ptr; + + + +class DebugLightClustersConfig : public render::Job::Config { + Q_OBJECT + Q_PROPERTY(int numDrawn READ getNumDrawn NOTIFY numDrawnChanged) + Q_PROPERTY(int maxDrawn MEMBER maxDrawn NOTIFY dirty) +public: + DebugLightClustersConfig() : render::Job::Config(true){} + + int getNumDrawn() { return numDrawn; } + void setNumDrawn(int num) { numDrawn = num; emit numDrawnChanged(); } + + int maxDrawn { -1 }; + +signals: + void numDrawnChanged(); + void dirty(); + +protected: + int numDrawn { 0 }; +}; + +class DebugLightClusters { +public: + // using Inputs = render::VaryingSet6 < DeferredFrameTransformPointer, DeferredFramebufferPointer, LightingModelPointer, SurfaceGeometryFramebufferPointer, AmbientOcclusionFramebufferPointer, SubsurfaceScatteringResourcePointer>; + using Config = DebugLightClustersConfig; + using JobModel = render::Job::Model; + + DebugLightClusters(); + + void configure(const Config& config); + + void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext); + +protected: + gpu::BufferPointer _gridBuffer; + gpu::PipelinePointer _drawClusterGrid; + const gpu::PipelinePointer getDrawClusterGridPipeline(); +}; + #endif diff --git a/libraries/render-utils/src/LightStage.h b/libraries/render-utils/src/LightStage.h index b0d5c1749f..c0632a0ebf 100644 --- a/libraries/render-utils/src/LightStage.h +++ b/libraries/render-utils/src/LightStage.h @@ -32,6 +32,8 @@ public: using Lights = render::indexed_container::IndexedPointerVector; using LightMap = std::unordered_map; + using LightIndices = std::vector; + class Shadow { public: using UniformBufferView = gpu::BufferView; diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 942419a8a4..6076cf697d 100755 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -190,6 +190,11 @@ RenderDeferredTask::RenderDeferredTask(CullFunctor cullFunctor) { addJob("DrawItemSelection", spatialSelection); } + // LIght Cluster Grid Debuging job + { + addJob("DebugLightClusters"); + } + // Status icon rendering job { // Grab a texture map representing the different status icons and assign that to the drawStatsuJob diff --git a/libraries/render-utils/src/RenderShadowTask.cpp b/libraries/render-utils/src/RenderShadowTask.cpp index 2efbe7bf89..aed360823d 100644 --- a/libraries/render-utils/src/RenderShadowTask.cpp +++ b/libraries/render-utils/src/RenderShadowTask.cpp @@ -36,12 +36,12 @@ void RenderShadowMap::run(const render::SceneContextPointer& sceneContext, const assert(renderContext->args); assert(renderContext->args->hasViewFrustum()); - const auto& lightStage = DependencyManager::get()->getLightStage(); + auto lightStage = DependencyManager::get()->getLightStage(); LightStage::Index globalLightIndex { 0 }; - const auto globalLight = lightStage.getLight(globalLightIndex); - const auto shadow = lightStage.getShadow(globalLightIndex); + const auto globalLight = lightStage->getLight(globalLightIndex); + const auto shadow = lightStage->getShadow(globalLightIndex); if (!shadow) return; const auto& fbo = shadow->framebuffer; @@ -144,8 +144,8 @@ void RenderShadowTask::run(const SceneContextPointer& sceneContext, const render return; } - const auto& lightStage = DependencyManager::get()->getLightStage(); - const auto globalShadow = lightStage.getShadow(0); + auto lightStage = DependencyManager::get()->getLightStage(); + const auto globalShadow = lightStage->getShadow(0); // If the global light is not set, bail if (!globalShadow) { diff --git a/libraries/render-utils/src/SubsurfaceScattering.cpp b/libraries/render-utils/src/SubsurfaceScattering.cpp index d78cbdb304..d49c388da3 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 light = DependencyManager::get()->getLightStage().getLight(0); + const auto light = DependencyManager::get()->getLightStage()->getLight(0); gpu::doInBatch(args->_context, [=](gpu::Batch& batch) { batch.enableStereo(false); diff --git a/libraries/render-utils/src/lightClusters_drawGrid.slf b/libraries/render-utils/src/lightClusters_drawGrid.slf new file mode 100644 index 0000000000..33c8cc56b8 --- /dev/null +++ b/libraries/render-utils/src/lightClusters_drawGrid.slf @@ -0,0 +1,19 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// lightClusters_drawGrid.slf +// +// Created by Sam Gateau on 9/8/2016. +// Copyright 2015 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 +// + +in vec4 varColor; +out vec4 outFragColor; + + +void main(void) { + outFragColor = varColor; +} diff --git a/libraries/render-utils/src/lightClusters_drawGrid.slv b/libraries/render-utils/src/lightClusters_drawGrid.slv new file mode 100644 index 0000000000..db7006322c --- /dev/null +++ b/libraries/render-utils/src/lightClusters_drawGrid.slv @@ -0,0 +1,89 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// lightClusters_drawGrid.slv +// Vertex shader +// +// Created by Sam Gateau on 9/8/2016 +// Copyright 2015 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 gpu/Transform.slh@> + +<$declareStandardTransform()$> + +<@include gpu/Color.slh@> +<$declareColorWheel()$> + + +struct FrustrumGrid { + vec4 nearFarRange; + ivec4 dims; + mat4 eyeToGridProj; + mat4 eyeToGridProjInv; + mat4 worldToEyeMat; + mat4 eyeToWorldMat; +}; + +uniform frustrumGridBuffer { + FrustrumGrid frustrumGrid; +}; + +//uniform ivec4 inClusterLocation; + +out vec4 varColor; + + +void main(void) { + const vec4 UNIT_BOX[8] = vec4[8]( + vec4(0.0, 0.0, 0.0, 1.0), + vec4(1.0, 0.0, 0.0, 1.0), + vec4(0.0, 1.0, 0.0, 1.0), + vec4(1.0, 1.0, 0.0, 1.0), + vec4(0.0, 0.0, 1.0, 1.0), + vec4(1.0, 0.0, 1.0, 1.0), + vec4(0.0, 1.0, 1.0, 1.0), + vec4(1.0, 1.0, 1.0, 1.0) + ); + const int UNIT_BOX_LINE_INDICES[24] = int[24]( + 0, 1, + 1, 3, + 3, 2, + 2, 0, + 4, 5, + 5, 7, + 7, 6, + 6, 4, + 2, 6, + 3, 7, + 0, 4, + 1, 5 + ); + vec4 pos = UNIT_BOX[UNIT_BOX_LINE_INDICES[gl_VertexID]]; + + // pos.z -= 10.0f; + + + vec4 eyePos = frustrumGrid.eyeToGridProjInv * (pos); + + eyePos.xyz *= eyePos.w; + + vec4 worldPos = frustrumGrid.eyeToWorldMat * vec4(eyePos.xyz, 1.0); + + /* + int cellIsEmpty = sign(inClusterLocation.w); + ivec4 cellLocation = ivec4(inClusterLocation.xyz, (inClusterLocation.w < 0 ? -inClusterLocation.w : inClusterLocation.w)); + vec4 cellBound = evalBound(cellLocation); + + pos.xyz = cellBound.xyz + vec3(cellBound.w) * pos.xyz; + */ + // standard transform + TransformCamera cam = getTransformCamera(); + <$transformWorldToClipPos(cam, worldPos, gl_Position)$> + + varColor = vec4(colorWheel(fract(float(gl_VertexID) / 24.0)), 0.9); +} \ No newline at end of file diff --git a/libraries/shared/src/ViewFrustum.cpp b/libraries/shared/src/ViewFrustum.cpp index 4a7d4eff95..0a1a41ace1 100644 --- a/libraries/shared/src/ViewFrustum.cpp +++ b/libraries/shared/src/ViewFrustum.cpp @@ -657,6 +657,26 @@ void ViewFrustum::evalProjectionMatrix(glm::mat4& proj) const { proj = _projection; } +glm::mat4 ViewFrustum::evalProjectionMatrixRange(float rangeNear, float rangeFar) const { + + // make sure range near far make sense + assert(rangeNear > 0.0); + assert(rangeFar > rangeNear); + + // recreate a projection matrix for only a range of depth of this frustum. + + // take the current projection + glm::mat4 rangeProj = _projection; + + float A = -(rangeFar + rangeNear) / (rangeFar - rangeNear); + float B = -2 * rangeFar*rangeNear / ((rangeFar - rangeNear)); + + rangeProj[2][2] = A; + rangeProj[3][2] = B; + return rangeProj; +} + + void ViewFrustum::evalViewTransform(Transform& view) const { view.setTranslation(getPosition()); view.setRotation(getOrientation()); diff --git a/libraries/shared/src/ViewFrustum.h b/libraries/shared/src/ViewFrustum.h index 48d45ab455..091aff7a92 100644 --- a/libraries/shared/src/ViewFrustum.h +++ b/libraries/shared/src/ViewFrustum.h @@ -129,6 +129,9 @@ public: float distanceToCamera(const glm::vec3& point) const; void evalProjectionMatrix(glm::mat4& proj) const; + + glm::mat4 evalProjectionMatrixRange(float rangeNear, float rangeFar) const; + void evalViewTransform(Transform& view) const; enum PlaneIndex { TOP_PLANE = 0, BOTTOM_PLANE, LEFT_PLANE, RIGHT_PLANE, NEAR_PLANE, FAR_PLANE, NUM_PLANES }; From 9bcaca057723fdf2cf9d1f78b3e0bdadef296e8e Mon Sep 17 00:00:00 2001 From: samcake Date: Thu, 8 Sep 2016 19:12:11 -0700 Subject: [PATCH 24/75] Developping the Light Clusters, adding visualization --- .../src/lightClusters_drawGrid.slv | 24 ++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/libraries/render-utils/src/lightClusters_drawGrid.slv b/libraries/render-utils/src/lightClusters_drawGrid.slv index db7006322c..4c32be6d5c 100644 --- a/libraries/render-utils/src/lightClusters_drawGrid.slv +++ b/libraries/render-utils/src/lightClusters_drawGrid.slv @@ -33,6 +33,18 @@ uniform frustrumGridBuffer { FrustrumGrid frustrumGrid; }; +float getProjectionNear(mat4 projection) { + float planeC = projection[2][3] + projection[2][2]; + float planeD = projection[3][2]; + return planeD / planeC; +} +float getProjectionFar(mat4 projection) { + //float planeA = projection[0][3] - projection[0][2]; + //float planeB = projection[1][3] - projection[1][2]; + float planeC = projection[2][3] - projection[2][2]; + float planeD = /*projection[3][3]*/ - projection[3][2]; + return planeD / planeC; +} //uniform ivec4 inClusterLocation; out vec4 varColor; @@ -66,14 +78,24 @@ void main(void) { vec4 pos = UNIT_BOX[UNIT_BOX_LINE_INDICES[gl_VertexID]]; // pos.z -= 10.0f; + vec3 cpos = vec3(1, 0, 1); + // float z = frustrumGrid.nearFarRange.y * (1 - pos.z) + frustrumGrid.nearFarRange.z * (pos.z); + vec3 gridScale = vec3(0.5, 0.5, 1.0) / vec3(frustrumGrid.dims.xyz); - vec4 eyePos = frustrumGrid.eyeToGridProjInv * (pos); + vec3 cvpos = cpos + pos.xyz; + + vec3 clusterStart = vec3(-1.0 + cvpos.x * gridScale.x, -1.0 + cvpos.y * gridScale.y, cvpos.z * gridScale.z); + + float z = getProjectionNear(frustrumGrid.eyeToGridProj) * (1 - clusterStart.z) + getProjectionFar(frustrumGrid.eyeToGridProj) * (clusterStart.z); + + vec4 eyePos = frustrumGrid.eyeToGridProjInv * (vec4(clusterStart.xy, 1.0, 1.0) * z); eyePos.xyz *= eyePos.w; vec4 worldPos = frustrumGrid.eyeToWorldMat * vec4(eyePos.xyz, 1.0); + /* int cellIsEmpty = sign(inClusterLocation.w); ivec4 cellLocation = ivec4(inClusterLocation.xyz, (inClusterLocation.w < 0 ? -inClusterLocation.w : inClusterLocation.w)); From a0d09e3316bcf0764a700ed4b0d6ce2789852982 Mon Sep 17 00:00:00 2001 From: samcake Date: Sat, 10 Sep 2016 10:14:31 -0700 Subject: [PATCH 25/75] Fixing the vizualisation shader for world to cluster space --- .../src/DeferredLightingEffect.cpp | 2 +- .../src/LightClusterGrid_shared.slh | 171 +++++++++--------- libraries/render-utils/src/LightClusters.cpp | 24 +-- libraries/render-utils/src/LightClusters.h | 13 +- .../render-utils/src/RenderDeferredTask.cpp | 14 +- .../lightClusters_drawClusterFromDepth.slf | 64 ++++--- .../render-utils/src/local_lights_shading.slf | 2 +- .../render/src/render/IndexedContainer.h | 4 +- 8 files changed, 162 insertions(+), 132 deletions(-) diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index c1f011fd79..7c81aeea22 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -705,7 +705,7 @@ void RenderDeferredLocals::run(const render::SceneContextPointer& sceneContext, static int frame = 0; frame++; - if (frame % 2000 == 0) { + if (frame % 1000 == 0) { lightClusters->updateFrustum(viewFrustum); lightClusters->updateVisibleLights(lightIndices); diff --git a/libraries/render-utils/src/LightClusterGrid_shared.slh b/libraries/render-utils/src/LightClusterGrid_shared.slh index c89d0e4c9b..37addee004 100644 --- a/libraries/render-utils/src/LightClusterGrid_shared.slh +++ b/libraries/render-utils/src/LightClusterGrid_shared.slh @@ -1,91 +1,98 @@ - // glsl / C++ compatible source as interface for FrustrumGrid +// glsl / C++ compatible source as interface for FrustrumGrid - int frustumGrid_numClusters() { - return frustumGrid.dims.x * frustumGrid.dims.y * frustumGrid.dims.z; +int frustumGrid_numClusters() { + return frustumGrid.dims.x * frustumGrid.dims.y * frustumGrid.dims.z; +} + + +float frustumGrid_depthRamp(float linear) { + // return linear; + return linear * linear; +} +float frustumGrid_depthRampInverse(float volume) { + // return volume; + return sqrt(volume); +} + +vec3 frustumGrid_gridToVolume(vec3 pos, ivec3 dims) { + vec3 gridScale = vec3(1.0, 1.0, 1.0) / vec3(dims); + vec3 volumePos = pos * gridScale; + volumePos.z = frustumGrid_depthRamp(volumePos.z); + return volumePos; +} + + +vec3 frustumGrid_volumeToGrid(vec3 vpos, ivec3 dims) { + vec3 gridPos = vec3(vpos.x, vpos.y, frustumGrid_depthRampInverse(vpos.z)) * vec3(dims); + return gridPos; +} + +vec4 frustumGrid_volumeToClip(vec3 vpos, float rangeNear, float rangeFar) { + vec3 ndcPos = vec3(-1.0 + 2.0 * vpos.x, -1.0 + 2.0 * vpos.y, vpos.z); + float depth = rangeNear * (1 - ndcPos.z) + rangeFar * (ndcPos.z); + vec4 clipPos = vec4(ndcPos.x * depth, ndcPos.y * depth, 1.0, depth); + return clipPos; +} + +vec3 frustumGrid_clipToEye(vec4 clipPos, mat4 projection) { + return vec3( + (clipPos.x + projection[2][0] * clipPos.w) / projection[0][0], + (clipPos.y + projection[2][1] * clipPos.w) / projection[1][1], + -clipPos.w + //, (clipPos.z - projection[3][3] * clipPos.w) / projection[3][2] + ); +} + +vec3 frustumGrid_volumeToEye(vec3 vpos, mat4 projection, float rangeNear, float rangeFar) { + return frustumGrid_clipToEye(frustumGrid_volumeToClip(vpos, rangeNear, rangeFar), projection); +} + + +vec3 frustumGrid_eyeToVolume(vec3 epos, mat4 projection, float rangeNear, float rangeFar) { + vec4 clipPos = vec4(epos.x * projection[0][0] + epos.z * projection[2][0], + epos.y * projection[1][1] + epos.z * projection[2][1], + epos.z * projection[2][2] + projection[2][3], + -epos.z); + vec4 ndcPos = clipPos / clipPos.w; + + vec3 volumePos = vec3(0.5 * (ndcPos.x + 1.0), 0.5 * (ndcPos.y + 1.0), (clipPos.w - rangeNear) / (rangeFar - rangeNear)); + return volumePos; +} + + +vec3 frustumGrid_clusterPosToEye(ivec3 clusterPos, vec3 offset) { + + vec3 cvpos = vec3(clusterPos) + offset; + + + vec3 volumePos = frustumGrid_gridToVolume(cvpos, frustumGrid.dims); + + vec3 eyePos = frustumGrid_volumeToEye(volumePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar); + + return eyePos; +} + + +ivec3 frustumGrid_eyeToClusterPos(vec3 eyePos) { + if ((eyePos.z > -frustumGrid.frustumNear) || (eyePos.z < -frustumGrid.frustumFar)) { + return ivec3(-1); } + + vec3 volumePos = frustumGrid_eyeToVolume(eyePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar); + + vec3 gridPos = frustumGrid_volumeToGrid(volumePos, frustumGrid.dims); - float frustumGrid_depthRamp(float linear) { - // return linear; - return linear * linear; - } - float frustumGrid_depthRampInverse(float volume) { - // return volume; - return sqrt(volume); - } + return ivec3(gridPos); +} - vec3 frustumGrid_gridToVolume(vec3 pos, ivec3 dims) { - vec3 gridScale = vec3(1.0, 1.0, 1.0) / vec3(dims); - vec3 volumePos = pos * gridScale; - volumePos.z = frustumGrid_depthRamp(volumePos.z); - return volumePos; - } +vec4 frustumGrid_eyeToWorld(vec4 eyePos) { + return frustumGrid.eyeToWorldMat * eyePos; +} - - vec3 frustumGrid_volumeToGrid(vec3 vpos, ivec3 dims) { - vec3 gridPos = vec3(vpos.x, vpos.y, frustumGrid_depthRampInverse(vpos.z)) * vec3(dims); - return gridPos; - } - - vec4 frustumGrid_volumeToClip(vec3 vpos, float rangeNear, float rangeFar) { - vec3 ndcPos = vec3(-1.0 + 2.0 * vpos.x, -1.0 + 2.0 * vpos.y, vpos.z); - float depth = rangeNear * (1 - ndcPos.z) + rangeFar * (ndcPos.z); - vec4 clipPos = vec4(ndcPos.x * depth, ndcPos.y * depth, 1.0, depth); - return clipPos; - } - - vec3 frustumGrid_clipToEye(vec4 clipPos, mat4 projection) { - return vec3( - (clipPos.x + projection[2][0] * clipPos.w) / projection[0][0], - (clipPos.y + projection[2][1] * clipPos.w) / projection[1][1], - -clipPos.w - //, (clipPos.z - projection[3][3] * clipPos.w) / projection[3][2] - ); - } - - vec3 frustumGrid_volumeToEye(vec3 vpos, mat4 projection, float rangeNear, float rangeFar) { - return frustumGrid_clipToEye(frustumGrid_volumeToClip(vpos, rangeNear, rangeFar), projection); - } - - - vec3 frustumGrid_eyeToVolume(vec3 epos, mat4 projection, float rangeNear, float rangeFar) { - vec4 clipPos = vec4(epos.x * projection[0][0] + epos.z * projection[2][0], - epos.y * projection[1][1] + epos.z * projection[2][1], - epos.z * projection[2][2] + projection[2][3], - -epos.z); - vec4 ndcPos = clipPos / clipPos.w; - - vec3 volumePos = vec3(0.5 * (ndcPos.x + 1.0), 0.5 * (ndcPos.y + 1.0), (clipPos.w - rangeNear) / (rangeFar - rangeNear)); - return volumePos; - } - - - vec3 frustumGrid_clusterPosToEye(ivec3 clusterPos, vec3 offset = vec3(0.5)) { - - vec3 cvpos = vec3(clusterPos) + offset; - - - vec3 volumePos = frustumGrid_gridToVolume(cvpos, frustumGrid.dims); - - vec3 eyePos = frustumGrid_volumeToEye(volumePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar); - - return eyePos; - } - - - ivec3 frustumGrid_eyeToClusterPos(vec3 eyePos) { - - vec3 volumePos = frustumGrid_eyeToVolume(eyePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar); - - vec3 gridPos = frustumGrid_volumeToGrid(volumePos, frustumGrid.dims); - - - return ivec3(gridPos); - } - - vec4 frustumGrid_eyeToWorld(vec4 eyePos) { - return frustumGrid.eyeToWorldMat * eyePos; - } +vec4 frustumGrid_worldToEye(vec4 worldPos) { + return frustumGrid.worldToEyeMat * worldPos; +} // <@if 1@> // Trigger Scribe include diff --git a/libraries/render-utils/src/LightClusters.cpp b/libraries/render-utils/src/LightClusters.cpp index faf50129c5..54902a104d 100644 --- a/libraries/render-utils/src/LightClusters.cpp +++ b/libraries/render-utils/src/LightClusters.cpp @@ -22,7 +22,7 @@ #include "lightClusters_drawClusterFromDepth_frag.h" enum LightClusterGridShader_MapSlot { - DEFERRED_BUFFER_LINEAR_DEPTH_UNIT = 7, + DEFERRED_BUFFER_LINEAR_DEPTH_UNIT = 0, }; enum LightClusterGridShader_BufferSlot { @@ -126,7 +126,7 @@ void DebugLightClusters::run(const render::SceneContextPointer& sceneContext, co auto deferredTransform = inputs.get0(); auto deferredFramebuffer = inputs.get1(); auto lightingModel = inputs.get2(); - auto surfaceGeometryFramebuffer = inputs.get3(); + auto linearDepthTarget = inputs.get3(); auto args = renderContext->args; @@ -149,21 +149,14 @@ void DebugLightClusters::run(const render::SceneContextPointer& sceneContext, co - if (true) { - // bind the one gpu::Pipeline we need - batch.setPipeline(getDrawClusterGridPipeline()); - auto dims = lightClusters->_frustumGridBuffer->dims; - glm::ivec3 summedDims(dims.x*dims.y * dims.z, dims.x*dims.y, dims.x); - batch.drawInstanced(summedDims.x, gpu::LINES, 24, 0); - } if (true) { batch.setPipeline(getDrawClusterFromDepthPipeline()); batch.setUniformBuffer(DEFERRED_FRAME_TRANSFORM_BUFFER_SLOT, deferredTransform->getFrameTransformBuffer()); - if (surfaceGeometryFramebuffer) { - batch.setResourceTexture(DEFERRED_BUFFER_LINEAR_DEPTH_UNIT, surfaceGeometryFramebuffer->getLinearDepthTexture()); + if (linearDepthTarget) { + batch.setResourceTexture(DEFERRED_BUFFER_LINEAR_DEPTH_UNIT, linearDepthTarget->getLinearDepthTexture()); } batch.draw(gpu::TRIANGLE_STRIP, 4, 0); @@ -173,7 +166,14 @@ void DebugLightClusters::run(const render::SceneContextPointer& sceneContext, co batch.setResourceTexture(DEFERRED_BUFFER_LINEAR_DEPTH_UNIT, nullptr); batch.setUniformBuffer(DEFERRED_FRAME_TRANSFORM_BUFFER_SLOT, nullptr); } - + if (true) { + // bind the one gpu::Pipeline we need + batch.setPipeline(getDrawClusterGridPipeline()); + + auto dims = lightClusters->_frustumGridBuffer->dims; + glm::ivec3 summedDims(dims.x*dims.y * dims.z, dims.x*dims.y, dims.x); + batch.drawInstanced(summedDims.x, gpu::LINES, 24, 0); + } args->_context->appendFrameBatch(batch); } \ No newline at end of file diff --git a/libraries/render-utils/src/LightClusters.h b/libraries/render-utils/src/LightClusters.h index 4491f5459d..474b238907 100644 --- a/libraries/render-utils/src/LightClusters.h +++ b/libraries/render-utils/src/LightClusters.h @@ -19,25 +19,28 @@ class FrustumGrid { public: - float _near { 0.1f }; + float frustumNear { 0.1f }; float rangeNear { 1.0f }; float rangeFar { 100.0f }; - float _far { 10000.0f }; + float frustumFar { 10000.0f }; glm::ivec3 dims { 8, 8, 8 }; float spare; glm::mat4 eyeToGridProj; - glm::mat4 _worldToEyeMat; + glm::mat4 worldToEyeMat; glm::mat4 eyeToWorldMat; void updateFrustum(const ViewFrustum& frustum) { + frustumNear = frustum.getNearClip(); + frustumFar = frustum.getFarClip(); + eyeToGridProj = frustum.evalProjectionMatrixRange(rangeNear, rangeFar); Transform view; frustum.evalViewTransform(view); eyeToWorldMat = view.getMatrix(); - _worldToEyeMat = view.getInverseMatrix(); + worldToEyeMat = view.getInverseMatrix(); } // Copy paste of the slh functions @@ -105,7 +108,7 @@ protected: class DebugLightClusters { public: - using Inputs = render::VaryingSet4 < DeferredFrameTransformPointer, DeferredFramebufferPointer, LightingModelPointer, SurfaceGeometryFramebufferPointer>; + using Inputs = render::VaryingSet4 < DeferredFrameTransformPointer, DeferredFramebufferPointer, LightingModelPointer, LinearDepthFramebufferPointer>; using Config = DebugLightClustersConfig; using JobModel = render::Job::ModelI; diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index f0438088ad..c683301c90 100755 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -154,7 +154,13 @@ RenderDeferredTask::RenderDeferredTask(CullFunctor cullFunctor) { // Use Stencil and draw background in Lighting buffer to complete filling in the opaque const auto backgroundInputs = DrawBackgroundDeferred::Inputs(background, lightingModel).hasVarying(); addJob("DrawBackgroundDeferred", backgroundInputs); - + + // LIght Cluster Grid Debuging job + { + const auto debugLightClustersInputs = DebugLightClusters::Inputs(deferredFrameTransform, deferredFramebuffer, lightingModel, linearDepthTarget).hasVarying(); + addJob("DebugLightClusters", debugLightClustersInputs); + } + // Render transparent objects forward in LightingBuffer const auto transparentsInputs = DrawDeferred::Inputs(transparents, lightingModel).hasVarying(); addJob("DrawTransparentDeferred", transparentsInputs, shapePlumber); @@ -190,11 +196,7 @@ RenderDeferredTask::RenderDeferredTask(CullFunctor cullFunctor) { addJob("DrawItemSelection", spatialSelection); } - // LIght Cluster Grid Debuging job - { - const auto debugLightClustersInputs = DebugLightClusters::Inputs(deferredFrameTransform, deferredFramebuffer, lightingModel, linearDepthTarget).hasVarying(); - addJob("DebugLightClusters", debugLightClustersInputs); - } + // Status icon rendering job { diff --git a/libraries/render-utils/src/lightClusters_drawClusterFromDepth.slf b/libraries/render-utils/src/lightClusters_drawClusterFromDepth.slf index a30fa78680..272f80c99f 100644 --- a/libraries/render-utils/src/lightClusters_drawClusterFromDepth.slf +++ b/libraries/render-utils/src/lightClusters_drawClusterFromDepth.slf @@ -21,7 +21,7 @@ <$declareColorWheel()$> -in vec4 varTexCoord0; +in vec2 varTexCoord0; out vec4 _fragColor; void main(void) { @@ -30,32 +30,50 @@ void main(void) { vec2 texCoord = varTexCoord0.st; float Zeye = texture(linearZeyeMap, texCoord).x; - _fragColor = vec4(vec3(0.1 * (10 - Zeye)), 1.0); - // return; + if (Zeye <= 0.1) { + return; + } + + // _fragColor = vec4(colorWheel(fract(0.1 * Zeye)),.5); + // return; vec4 fragPosition = unpackDeferredPositionFromZeye(texCoord); - -// return; - - ivec3 dims = frustumGrid.dims.xyz; - - ivec3 summedDims = ivec3(dims.x * dims.y, dims.x, 1); - - - vec3 eyePos = fragPosition.xyz; - + // Frag pos in world + vec4 fragWorldPos = getViewInverse() * fragPosition; + + // From frag world pos find the cluster + //vec3 fragEyePos = fragPosition.xyz; + // vec4 worldPos = frustumGrid_eyeToWorld(vec4(eyePos.xyz, 1.0)); + vec4 clusterEyePos = frustumGrid_worldToEye(fragWorldPos); + ivec3 clusterPos = frustumGrid_eyeToClusterPos(clusterEyePos.xyz); - ivec3 clusterPos = frustumGrid_eyeToClusterPos(eyePos); - - - // standard transform - // TransformCamera cam = getTransformCamera(); - // <$transformWorldToClipPos(cam, worldPos, gl_Position)$> - - _fragColor = vec4(colorWheel(fract(float(clusterPos.z * summedDims.x + clusterPos.y * summedDims.y + clusterPos.x) / float(frustumGrid_numClusters()))), 0.9); - _fragColor = vec4(abs(fract(eyePos * 0.5)), 0.9); - + ivec3 dims = frustumGrid.dims.xyz; + ivec3 summedDims = ivec3(dims.x * dims.y, dims.x, 1); + + if (clusterPos.x < 0 || clusterPos.x >= dims.x) { + _fragColor = vec4(0.0); + return; + } + + if (clusterPos.y < 0 || clusterPos.y >= dims.y) { + _fragColor = vec4(0.0); + return; + } + if (clusterPos.z < 0 || clusterPos.z >= dims.z) { + _fragColor = vec4(0.0); + return; + } + + float relClusterId = float(clusterPos.z * summedDims.x + clusterPos.y * summedDims.y + clusterPos.x) / float(frustumGrid_numClusters()); + + if (relClusterId < 0.0) { + _fragColor = vec4(0.0); + } else if (relClusterId >= 1.0) { + _fragColor = vec4(vec3(1.0), 0.5); + } else { + _fragColor = vec4(colorWheel(fract(relClusterId)), 0.9); + } } diff --git a/libraries/render-utils/src/local_lights_shading.slf b/libraries/render-utils/src/local_lights_shading.slf index d5a759d7c0..c3e41fb672 100644 --- a/libraries/render-utils/src/local_lights_shading.slf +++ b/libraries/render-utils/src/local_lights_shading.slf @@ -30,7 +30,7 @@ uniform lightIndexBuffer { <@include LightSpot.slh@> <$declareLightingSpot(supportScattering)$> -in vec4 _texCoord0; +in vec2 _texCoord0; out vec4 _fragColor; void main(void) { diff --git a/libraries/render/src/render/IndexedContainer.h b/libraries/render/src/render/IndexedContainer.h index 847fb53bdf..6250d4f4f1 100644 --- a/libraries/render/src/render/IndexedContainer.h +++ b/libraries/render/src/render/IndexedContainer.h @@ -117,10 +117,10 @@ namespace indexed_container { Index newElement(const ElementPtr& e) { Index index = _allocator.allocateIndex(); if (index != INVALID_INDEX) { - if (index < _elements.size()) { + if (index < (Index) _elements.size()) { _elements.emplace(_elements.begin() + index, e); } else { - assert(index == _elements.size()); + assert(index == (Index) _elements.size()); _elements.emplace_back(e); } } From 7a7a60a5c497b89d78f1f3ba6a0c1a53657e9c66 Mon Sep 17 00:00:00 2001 From: samcake Date: Sun, 11 Sep 2016 00:17:34 -0700 Subject: [PATCH 26/75] INtroducing a true stage for updating the light cluster and ui to debug --- .../src/DeferredLightingEffect.cpp | 41 ++++----- .../render-utils/src/DeferredLightingEffect.h | 7 +- .../src/LightClusterGrid_shared.slh | 18 ++-- libraries/render-utils/src/LightClusters.cpp | 88 ++++++++++++++++--- libraries/render-utils/src/LightClusters.h | 79 +++++++++++++---- .../render-utils/src/RenderDeferredTask.cpp | 24 +++-- .../lightClusters_drawClusterFromDepth.slf | 20 +---- .../render-utils/src/local_lights_shading.slf | 4 +- libraries/render/src/render/Task.h | 34 +++++++ .../utilities/render/lightClustering.js | 21 +++++ .../utilities/render/lightClustering.qml | 45 ++++++++++ 11 files changed, 292 insertions(+), 89 deletions(-) create mode 100644 scripts/developer/utilities/render/lightClustering.js create mode 100644 scripts/developer/utilities/render/lightClustering.qml diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index 7c81aeea22..e6ca901376 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -634,7 +634,7 @@ void RenderDeferredSetup::run(const render::SceneContextPointer& sceneContext, c } RenderDeferredLocals::RenderDeferredLocals() : -_localLightsBuffer(std::make_shared()) { + _localLightsBuffer(std::make_shared()) { } @@ -642,7 +642,7 @@ void RenderDeferredLocals::run(const render::SceneContextPointer& sceneContext, const DeferredFrameTransformPointer& frameTransform, const DeferredFramebufferPointer& deferredFramebuffer, const LightingModelPointer& lightingModel, - const SurfaceGeometryFramebufferPointer& surfaceGeometryFramebuffer) { + const SurfaceGeometryFramebufferPointer& surfaceGeometryFramebuffer, const LightClustersPointer& lightClusters) { bool points = lightingModel->isPointLightEnabled(); bool spots = lightingModel->isSpotLightEnabled(); @@ -676,18 +676,17 @@ void RenderDeferredLocals::run(const render::SceneContextPointer& sceneContext, auto textureFrameTransform = gpu::Framebuffer::evalSubregionTexcoordTransformCoefficients(deferredFramebuffer->getFrameSize(), viewport); - batch.setProjectionTransform(projMat); - batch.setViewTransform(viewTransform, true); + // batch.setProjectionTransform(projMat); + // batch.setViewTransform(viewTransform, true); // gather lights - auto& srcPointLights = deferredLightingEffect->_pointLights; + /* auto& srcPointLights = deferredLightingEffect->_pointLights; auto& srcSpotLights = deferredLightingEffect->_spotLights; int numPointLights = (int) srcPointLights.size(); int offsetPointLights = 0; int numSpotLights = (int) srcSpotLights.size(); int offsetSpotLights = numPointLights; - auto lightClusters = deferredLightingEffect->_lightClusters; std::vector lightIndices(numPointLights + numSpotLights + 1); lightIndices[0] = 0; @@ -699,28 +698,21 @@ void RenderDeferredLocals::run(const render::SceneContextPointer& sceneContext, if (spots && !srcSpotLights.empty()) { memcpy(lightIndices.data() + (lightIndices[0] + 1), srcSpotLights.data(), srcSpotLights.size() * sizeof(int)); lightIndices[0] += (int)srcSpotLights.size(); - } - - if (lightIndices[0] > 0) { - static int frame = 0; - frame++; - - if (frame % 1000 == 0) { - lightClusters->updateFrustum(viewFrustum); - - lightClusters->updateVisibleLights(lightIndices); - } - _localLightsBuffer._buffer->setData(lightIndices.size() * sizeof(int), (const gpu::Byte*) lightIndices.data()); - _localLightsBuffer._size = lightIndices.size() * sizeof(int); + }*/ + //auto lightClusters = deferredLightingEffect->_lightClusters; + auto& lightIndices = lightClusters->_visibleLightIndices; + if (!lightIndices.empty() && lightIndices[0] > 0) { + // _localLightsBuffer._buffer->setData(lightIndices.size() * sizeof(int), (const gpu::Byte*) lightIndices.data()); + // _localLightsBuffer._size = lightIndices.size() * sizeof(int); // Bind the global list of lights and the visible lights this frame - batch.setUniformBuffer(deferredLightingEffect->_localLightLocations->lightBufferUnit, deferredLightingEffect->getLightStage()->_lightArrayBuffer); - batch.setUniformBuffer(deferredLightingEffect->_localLightLocations->lightIndexBufferUnit, _localLightsBuffer); + batch.setUniformBuffer(deferredLightingEffect->_localLightLocations->lightBufferUnit, lightClusters->_lightStage->_lightArrayBuffer); + batch.setUniformBuffer(deferredLightingEffect->_localLightLocations->lightIndexBufferUnit, lightClusters->_lightIndicesBuffer); // before we get to the real lighting, let s try to cull down the number of pixels - if (false) { + if (false) {/* if (numPointLights > 0) { auto mesh = deferredLightingEffect->getPointLightMesh(); batch.setIndexBuffer(mesh->getIndexBuffer()); @@ -753,7 +745,7 @@ void RenderDeferredLocals::run(const render::SceneContextPointer& sceneContext, batch.setPipeline(deferredLightingEffect->_spotLightFront); batch.drawIndexedInstanced(numSpotLights, model::Mesh::topologyToPrimitive(conePart._topology), conePart._numIndices, conePart._startIndex, offsetSpotLights); - } + }*/ } // Local light pipeline @@ -815,6 +807,7 @@ void RenderDeferred::run(const SceneContextPointer& sceneContext, const RenderCo auto surfaceGeometryFramebuffer = inputs.get3(); auto ssaoFramebuffer = inputs.get4(); auto subsurfaceScatteringResource = inputs.get5(); + auto lightClusters = inputs.get6(); auto args = renderContext->args; if (!_gpuTimer) { @@ -828,7 +821,7 @@ void RenderDeferred::run(const SceneContextPointer& sceneContext, const RenderCo setupJob.run(sceneContext, renderContext, deferredTransform, deferredFramebuffer, lightingModel, surfaceGeometryFramebuffer, ssaoFramebuffer, subsurfaceScatteringResource); - lightsJob.run(sceneContext, renderContext, deferredTransform, deferredFramebuffer, lightingModel, surfaceGeometryFramebuffer); + lightsJob.run(sceneContext, renderContext, deferredTransform, deferredFramebuffer, lightingModel, surfaceGeometryFramebuffer, lightClusters); cleanupJob.run(sceneContext, renderContext); diff --git a/libraries/render-utils/src/DeferredLightingEffect.h b/libraries/render-utils/src/DeferredLightingEffect.h index ce29480950..a66a2ed2ed 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.h +++ b/libraries/render-utils/src/DeferredLightingEffect.h @@ -117,7 +117,7 @@ private: std::vector _pointLights; std::vector _spotLights; - + friend class LightClusteringPass; friend class RenderDeferredSetup; friend class RenderDeferredLocals; friend class RenderDeferredCleanup; @@ -167,7 +167,8 @@ public: const DeferredFrameTransformPointer& frameTransform, const DeferredFramebufferPointer& deferredFramebuffer, const LightingModelPointer& lightingModel, - const SurfaceGeometryFramebufferPointer& surfaceGeometryFramebuffer); + const SurfaceGeometryFramebufferPointer& surfaceGeometryFramebuffer, + const LightClustersPointer& lightClusters); gpu::BufferView _localLightsBuffer; @@ -187,7 +188,7 @@ using RenderDeferredConfig = render::GPUJobConfig; class RenderDeferred { public: - using Inputs = render::VaryingSet6 < DeferredFrameTransformPointer, DeferredFramebufferPointer, LightingModelPointer, SurfaceGeometryFramebufferPointer, AmbientOcclusionFramebufferPointer, SubsurfaceScatteringResourcePointer>; + using Inputs = render::VaryingSet7 < DeferredFrameTransformPointer, DeferredFramebufferPointer, LightingModelPointer, SurfaceGeometryFramebufferPointer, AmbientOcclusionFramebufferPointer, SubsurfaceScatteringResourcePointer, LightClustersPointer>; using Config = RenderDeferredConfig; using JobModel = render::Job::ModelI; diff --git a/libraries/render-utils/src/LightClusterGrid_shared.slh b/libraries/render-utils/src/LightClusterGrid_shared.slh index 37addee004..5ccba9a786 100644 --- a/libraries/render-utils/src/LightClusterGrid_shared.slh +++ b/libraries/render-utils/src/LightClusterGrid_shared.slh @@ -1,10 +1,5 @@ // glsl / C++ compatible source as interface for FrustrumGrid -int frustumGrid_numClusters() { - return frustumGrid.dims.x * frustumGrid.dims.y * frustumGrid.dims.z; -} - - float frustumGrid_depthRamp(float linear) { // return linear; return linear * linear; @@ -60,6 +55,11 @@ vec3 frustumGrid_eyeToVolume(vec3 epos, mat4 projection, float rangeNear, float } + +int frustumGrid_numClusters() { + return frustumGrid.dims.x * frustumGrid.dims.y * (frustumGrid.dims.z); +} + vec3 frustumGrid_clusterPosToEye(ivec3 clusterPos, vec3 offset) { vec3 cvpos = vec3(clusterPos) + offset; @@ -78,9 +78,17 @@ ivec3 frustumGrid_eyeToClusterPos(vec3 eyePos) { return ivec3(-1); } + if (eyePos.z > -frustumGrid.rangeNear) { + return ivec3(0,0,-1); + } + vec3 volumePos = frustumGrid_eyeToVolume(eyePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar); vec3 gridPos = frustumGrid_volumeToGrid(volumePos, frustumGrid.dims); + + if (gridPos.z >= frustumGrid.dims.z) { + gridPos.z = frustumGrid.dims.z; + } return ivec3(gridPos); diff --git a/libraries/render-utils/src/LightClusters.cpp b/libraries/render-utils/src/LightClusters.cpp index 54902a104d..e98322da4d 100644 --- a/libraries/render-utils/src/LightClusters.cpp +++ b/libraries/render-utils/src/LightClusters.cpp @@ -35,7 +35,8 @@ enum LightClusterGridShader_BufferSlot { #include "DeferredLightingEffect.h" -LightClusters::LightClusters() { +LightClusters::LightClusters() : +_lightIndicesBuffer(std::make_shared()) { } void LightClusters::updateFrustum(const ViewFrustum& frustum) { @@ -49,12 +50,77 @@ void LightClusters::updateLightStage(const LightStagePointer& lightStage) { } void LightClusters::updateVisibleLights(const LightStage::LightIndices& visibleLights) { - + + _visibleLightIndices.clear(); + // _lightClusters->_visibleLightIndices.push_back(0); + _visibleLightIndices = visibleLights; + _lightIndicesBuffer._buffer->setData(_visibleLightIndices.size() * sizeof(int), (const gpu::Byte*) _visibleLightIndices.data()); + _lightIndicesBuffer._size = _visibleLightIndices.size() * sizeof(int); } +LightClusteringPass::LightClusteringPass() { +} +void LightClusteringPass::configure(const Config& config) { + if (_lightClusters) { + if (_lightClusters->_frustumGridBuffer->rangeNear != config.rangeNear) { + _lightClusters->_frustumGridBuffer.edit().rangeNear = config.rangeNear; + } + if (_lightClusters->_frustumGridBuffer->rangeFar != config.rangeFar) { + _lightClusters->_frustumGridBuffer.edit().rangeFar = config.rangeFar; + } + } + + _freeze = config.freeze; +} + +void LightClusteringPass::run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext, const Inputs& inputs, Outputs& output) { + auto args = renderContext->args; + + auto deferredTransform = inputs.get0(); + auto lightingModel = inputs.get1(); + auto surfaceGeometryFramebuffer = inputs.get2(); + + bool points = lightingModel->isPointLightEnabled(); + bool spots = lightingModel->isSpotLightEnabled(); + auto deferredLightingEffect = DependencyManager::get(); + + if (!_lightClusters) { + _lightClusters = deferredLightingEffect->getLightClusters(); + } + + // first update the Grid with the new frustum + if (!_freeze) { + _lightClusters->updateFrustum(args->getViewFrustum()); + } + + // Now gather the lights + // gather lights + auto& srcPointLights = deferredLightingEffect->_pointLights; + auto& srcSpotLights = deferredLightingEffect->_spotLights; + int numPointLights = (int) srcPointLights.size(); + int offsetPointLights = 0; + int numSpotLights = (int) srcSpotLights.size(); + int offsetSpotLights = numPointLights; + + std::vector lightIndices(numPointLights + numSpotLights + 1); + lightIndices[0] = 0; + + if (points && !srcPointLights.empty()) { + memcpy(lightIndices.data() + (lightIndices[0] + 1), srcPointLights.data(), srcPointLights.size() * sizeof(int)); + lightIndices[0] += (int)srcPointLights.size(); + } + if (spots && !srcSpotLights.empty()) { + memcpy(lightIndices.data() + (lightIndices[0] + 1), srcSpotLights.data(), srcSpotLights.size() * sizeof(int)); + lightIndices[0] += (int)srcSpotLights.size(); + } + + _lightClusters->updateVisibleLights(lightIndices); + + output = _lightClusters; +} DebugLightClusters::DebugLightClusters() { @@ -62,6 +128,9 @@ DebugLightClusters::DebugLightClusters() { void DebugLightClusters::configure(const Config& config) { + doDrawGrid = config.doDrawGrid; + doDrawClusterFromDepth = config.doDrawClusterFromDepth; + } const gpu::PipelinePointer DebugLightClusters::getDrawClusterGridPipeline() { @@ -119,15 +188,12 @@ const gpu::PipelinePointer DebugLightClusters::getDrawClusterFromDepthPipeline() } void DebugLightClusters::run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext, const Inputs& inputs) { - auto deferredLightingEffect = DependencyManager::get(); - auto lightClusters = deferredLightingEffect->getLightClusters(); - - auto deferredTransform = inputs.get0(); auto deferredFramebuffer = inputs.get1(); auto lightingModel = inputs.get2(); auto linearDepthTarget = inputs.get3(); - + auto lightClusters = inputs.get4(); + auto args = renderContext->args; gpu::Batch batch; @@ -148,10 +214,7 @@ void DebugLightClusters::run(const render::SceneContextPointer& sceneContext, co batch.setUniformBuffer(LIGHT_CLUSTER_GRID_FRUSTUM_GRID_SLOT, lightClusters->_frustumGridBuffer); - - - - if (true) { + if (doDrawClusterFromDepth) { batch.setPipeline(getDrawClusterFromDepthPipeline()); batch.setUniformBuffer(DEFERRED_FRAME_TRANSFORM_BUFFER_SLOT, deferredTransform->getFrameTransformBuffer()); @@ -166,7 +229,8 @@ void DebugLightClusters::run(const render::SceneContextPointer& sceneContext, co batch.setResourceTexture(DEFERRED_BUFFER_LINEAR_DEPTH_UNIT, nullptr); batch.setUniformBuffer(DEFERRED_FRAME_TRANSFORM_BUFFER_SLOT, nullptr); } - if (true) { + + if (doDrawGrid) { // bind the one gpu::Pipeline we need batch.setPipeline(getDrawClusterGridPipeline()); diff --git a/libraries/render-utils/src/LightClusters.h b/libraries/render-utils/src/LightClusters.h index 474b238907..0cfaea5ef5 100644 --- a/libraries/render-utils/src/LightClusters.h +++ b/libraries/render-utils/src/LightClusters.h @@ -72,43 +72,84 @@ public: gpu::StructBuffer _frustumGridBuffer; - - gpu::BufferPointer _lightIndicesBuffer; + LightStage::LightIndices _visibleLightIndices; + + gpu::BufferView _lightIndicesBuffer; }; using LightClustersPointer = std::shared_ptr; -class DebugLightClustersConfig : public render::Job::Config { +class LightClusteringPassConfig : public render::Job::Config { Q_OBJECT - Q_PROPERTY(int numDrawn READ getNumDrawn NOTIFY numDrawnChanged) - Q_PROPERTY(int maxDrawn MEMBER maxDrawn NOTIFY dirty) + Q_PROPERTY(float rangeNear MEMBER rangeNear NOTIFY dirty) + Q_PROPERTY(float rangeFar MEMBER rangeFar NOTIFY dirty) + + Q_PROPERTY(bool freeze MEMBER freeze NOTIFY dirty) public: - DebugLightClustersConfig() : render::Job::Config(true){} - - int getNumDrawn() { return numDrawn; } - void setNumDrawn(int num) { numDrawn = num; emit numDrawnChanged(); } - - int maxDrawn { -1 }; - + LightClusteringPassConfig() : render::Job::Config(true){} + float rangeNear{ 1.0f }; + float rangeFar{ 512.0f }; + bool freeze{ false }; + signals: - void numDrawnChanged(); void dirty(); - + protected: - int numDrawn { 0 }; }; - #include "DeferredFrameTransform.h" -#include "DeferredFramebuffer.h" #include "LightingModel.h" #include "SurfaceGeometryPass.h" +class LightClusteringPass { +public: + using Inputs = render::VaryingSet3; + using Outputs = LightClustersPointer; + using Config = LightClusteringPassConfig; + using JobModel = render::Job::ModelIO; + + LightClusteringPass(); + + void configure(const Config& config); + + void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext, const Inputs& inputs, Outputs& output); + +protected: + LightClustersPointer _lightClusters; + bool _freeze; +}; + + + + + + + +class DebugLightClustersConfig : public render::Job::Config { + Q_OBJECT + Q_PROPERTY(bool doDrawGrid MEMBER doDrawGrid NOTIFY dirty) + Q_PROPERTY(bool doDrawClusterFromDepth MEMBER doDrawClusterFromDepth NOTIFY dirty) +public: + DebugLightClustersConfig() : render::Job::Config(true){} + + + bool doDrawGrid{ false }; + bool doDrawClusterFromDepth{ false }; + +signals: + void dirty(); + +protected: +}; + + +#include "DeferredFramebuffer.h" + class DebugLightClusters { public: - using Inputs = render::VaryingSet4 < DeferredFrameTransformPointer, DeferredFramebufferPointer, LightingModelPointer, LinearDepthFramebufferPointer>; + using Inputs = render::VaryingSet5 < DeferredFrameTransformPointer, DeferredFramebufferPointer, LightingModelPointer, LinearDepthFramebufferPointer, LightClustersPointer>; using Config = DebugLightClustersConfig; using JobModel = render::Job::ModelI; @@ -124,6 +165,8 @@ protected: gpu::PipelinePointer _drawClusterFromDepth; const gpu::PipelinePointer getDrawClusterGridPipeline(); const gpu::PipelinePointer getDrawClusterFromDepthPipeline(); + bool doDrawGrid{ false }; + bool doDrawClusterFromDepth{ false }; }; #endif diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index c683301c90..c959743b57 100755 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -142,29 +142,37 @@ RenderDeferredTask::RenderDeferredTask(CullFunctor cullFunctor) { const auto ambientOcclusionFramebuffer = ambientOcclusionOutputs.getN(0); const auto ambientOcclusionUniforms = ambientOcclusionOutputs.getN(1); + // Draw Lights just add the lights to the current list of lights to deal with. NOt really gpu job for now. addJob("DrawLight", lights); - const auto deferredLightingInputs = RenderDeferred::Inputs(deferredFrameTransform, deferredFramebuffer, lightingModel, - surfaceGeometryFramebuffer, ambientOcclusionFramebuffer, scatteringResource).hasVarying(); + // Light Clustering + // Create the cluster grid of lights, cpu job for now + const auto lightClusteringPassInputs = LightClusteringPass::Inputs(deferredFrameTransform, lightingModel, linearDepthTarget).hasVarying(); + const auto lightClusters = addJob("LightClustering", lightClusteringPassInputs); + // DeferredBuffer is complete, now let's shade it into the LightingBuffer + const auto deferredLightingInputs = RenderDeferred::Inputs(deferredFrameTransform, deferredFramebuffer, lightingModel, + surfaceGeometryFramebuffer, ambientOcclusionFramebuffer, scatteringResource, lightClusters).hasVarying(); + addJob("RenderDeferred", deferredLightingInputs); // Use Stencil and draw background in Lighting buffer to complete filling in the opaque const auto backgroundInputs = DrawBackgroundDeferred::Inputs(background, lightingModel).hasVarying(); addJob("DrawBackgroundDeferred", backgroundInputs); - // LIght Cluster Grid Debuging job - { - const auto debugLightClustersInputs = DebugLightClusters::Inputs(deferredFrameTransform, deferredFramebuffer, lightingModel, linearDepthTarget).hasVarying(); - addJob("DebugLightClusters", debugLightClustersInputs); - } // Render transparent objects forward in LightingBuffer const auto transparentsInputs = DrawDeferred::Inputs(transparents, lightingModel).hasVarying(); addJob("DrawTransparentDeferred", transparentsInputs, shapePlumber); + // LIght Cluster Grid Debuging job + { + const auto debugLightClustersInputs = DebugLightClusters::Inputs(deferredFrameTransform, deferredFramebuffer, lightingModel, linearDepthTarget, lightClusters).hasVarying(); + addJob("DebugLightClusters", debugLightClustersInputs); + } + const auto toneAndPostRangeTimer = addJob("BeginToneAndPostRangeTimer", "PostToneOverlaysAntialiasing"); // Lighting Buffer ready for tone mapping @@ -196,8 +204,6 @@ RenderDeferredTask::RenderDeferredTask(CullFunctor cullFunctor) { addJob("DrawItemSelection", spatialSelection); } - - // Status icon rendering job { // Grab a texture map representing the different status icons and assign that to the drawStatsuJob diff --git a/libraries/render-utils/src/lightClusters_drawClusterFromDepth.slf b/libraries/render-utils/src/lightClusters_drawClusterFromDepth.slf index 272f80c99f..cd4f7fee63 100644 --- a/libraries/render-utils/src/lightClusters_drawClusterFromDepth.slf +++ b/libraries/render-utils/src/lightClusters_drawClusterFromDepth.slf @@ -29,27 +29,15 @@ void main(void) { // Grab the fragment data from the uv vec2 texCoord = varTexCoord0.st; - float Zeye = texture(linearZeyeMap, texCoord).x; - if (Zeye <= 0.1) { - return; - } - - // _fragColor = vec4(colorWheel(fract(0.1 * Zeye)),.5); - // return; - - vec4 fragPosition = unpackDeferredPositionFromZeye(texCoord); - - // Frag pos in world - vec4 fragWorldPos = getViewInverse() * fragPosition; + vec4 fragEyePos = unpackDeferredPositionFromZeye(texCoord); + vec4 fragWorldPos = getViewInverse() * fragEyePos; // From frag world pos find the cluster - //vec3 fragEyePos = fragPosition.xyz; - - // vec4 worldPos = frustumGrid_eyeToWorld(vec4(eyePos.xyz, 1.0)); vec4 clusterEyePos = frustumGrid_worldToEye(fragWorldPos); ivec3 clusterPos = frustumGrid_eyeToClusterPos(clusterEyePos.xyz); ivec3 dims = frustumGrid.dims.xyz; + dims.z +=1; ivec3 summedDims = ivec3(dims.x * dims.y, dims.x, 1); if (clusterPos.x < 0 || clusterPos.x >= dims.x) { @@ -61,7 +49,7 @@ void main(void) { _fragColor = vec4(0.0); return; } - if (clusterPos.z < 0 || clusterPos.z >= dims.z) { + if (clusterPos.z < 0 || clusterPos.z > dims.z) { _fragColor = vec4(0.0); return; } diff --git a/libraries/render-utils/src/local_lights_shading.slf b/libraries/render-utils/src/local_lights_shading.slf index c3e41fb672..b002382c91 100644 --- a/libraries/render-utils/src/local_lights_shading.slf +++ b/libraries/render-utils/src/local_lights_shading.slf @@ -19,9 +19,9 @@ // Everything about light <@include model/Light.slh@> -<$declareLightBuffer(32)$> +<$declareLightBuffer(128)$> uniform lightIndexBuffer { - int lightIndex[32]; + int lightIndex[128]; }; <@include LightingModel.slh@> diff --git a/libraries/render/src/render/Task.h b/libraries/render/src/render/Task.h index df24a08c05..16315de523 100644 --- a/libraries/render/src/render/Task.h +++ b/libraries/render/src/render/Task.h @@ -254,6 +254,40 @@ public: Varying hasVarying() const { return Varying((*this)); } }; +template +class VaryingSet7 : public std::tuple{ +public: + using Parent = std::tuple; + + VaryingSet7() : Parent(Varying(T0()), Varying(T1()), Varying(T2()), Varying(T3()), Varying(T4()), Varying(T5()), Varying(T6())) {} + VaryingSet7(const VaryingSet7& src) : Parent(std::get<0>(src), std::get<1>(src), std::get<2>(src), std::get<3>(src), std::get<4>(src), std::get<5>(src), std::get<6>(src)) {} + VaryingSet7(const Varying& first, const Varying& second, const Varying& third, const Varying& fourth, const Varying& fifth, const Varying& sixth, const Varying& seventh) : Parent(first, second, third, fourth, fifth, sixth, seventh) {} + + const T0& get0() const { return std::get<0>((*this)).template get(); } + T0& edit0() { return std::get<0>((*this)).template edit(); } + + const T1& get1() const { return std::get<1>((*this)).template get(); } + T1& edit1() { return std::get<1>((*this)).template edit(); } + + const T2& get2() const { return std::get<2>((*this)).template get(); } + T2& edit2() { return std::get<2>((*this)).template edit(); } + + const T3& get3() const { return std::get<3>((*this)).template get(); } + T3& edit3() { return std::get<3>((*this)).template edit(); } + + const T4& get4() const { return std::get<4>((*this)).template get(); } + T4& edit4() { return std::get<4>((*this)).template edit(); } + + const T5& get5() const { return std::get<5>((*this)).template get(); } + T5& edit5() { return std::get<5>((*this)).template edit(); } + + const T6& get6() const { return std::get<6>((*this)).template get(); } + T6& edit6() { return std::get<6>((*this)).template edit(); } + + Varying hasVarying() const { return Varying((*this)); } +}; + + template < class T, int NUM > class VaryingArray : public std::array { public: diff --git a/scripts/developer/utilities/render/lightClustering.js b/scripts/developer/utilities/render/lightClustering.js new file mode 100644 index 0000000000..bad023a64f --- /dev/null +++ b/scripts/developer/utilities/render/lightClustering.js @@ -0,0 +1,21 @@ +// +// lightClustering.js +// examples/utilities/tools/render +// +// Sam Gateau, created on 9/9/2016. +// Copyright 2016 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 +// + +// Set up the qml ui +var qml = Script.resolvePath('lightClustering.qml'); +var window = new OverlayWindow({ + title: 'Light Clustering', + source: qml, + width: 400, + height: 200 +}); +window.setPosition(Window.innerWidth - 420, 50 + 250 + 50); +window.closed.connect(function() { Script.stop(); }); \ No newline at end of file diff --git a/scripts/developer/utilities/render/lightClustering.qml b/scripts/developer/utilities/render/lightClustering.qml new file mode 100644 index 0000000000..be252441db --- /dev/null +++ b/scripts/developer/utilities/render/lightClustering.qml @@ -0,0 +1,45 @@ +// +// lightClustering.qml +// +// Created by Sam Gateau on 9/9/2016 +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html +// +import QtQuick 2.5 +import QtQuick.Controls 1.4 +import "configSlider" + +Column { + spacing: 8 + Column { + id: lightClustering + spacing: 10 + + Column{ + ConfigSlider { + label: qsTr("Range Near [m]") + integral: false + config: Render.getConfig("LightClustering") + property: "rangeNear" + max: 20.0 + min: 0.1 + } + ConfigSlider { + label: qsTr("Range Far [m]") + integral: false + config: Render.getConfig("LightClustering") + property: "rangeFar" + max: 500.0 + min: 100.0 + } + + CheckBox { + text: "Freeze" + checked: Render.getConfig("LightClustering")["freeze"] + onCheckedChanged: { Render.getConfig("LightClustering")["freeze"] = checked } + } + } + } +} From 821072bb763aba451235166e2f2e51119d0b8f39 Mon Sep 17 00:00:00 2001 From: samcake Date: Mon, 12 Sep 2016 11:07:55 -0700 Subject: [PATCH 27/75] REarrange the light stage construction and light frame usage to produce the light clusters --- libraries/model/src/model/Light.h | 2 +- libraries/model/src/model/Light.slh | 2 +- .../src/DeferredLightingEffect.cpp | 11 +++- .../render-utils/src/DeferredLightingEffect.h | 3 - libraries/render-utils/src/LightClusters.cpp | 65 ++++++++++--------- libraries/render-utils/src/LightClusters.h | 5 +- libraries/render-utils/src/LightPayload.cpp | 31 +++++++-- libraries/render-utils/src/LightPayload.h | 12 ++-- libraries/render-utils/src/LightStage.cpp | 10 +++ libraries/render-utils/src/LightStage.h | 31 ++++++++- .../utilities/render/lightClustering.qml | 10 +++ 11 files changed, 130 insertions(+), 52 deletions(-) diff --git a/libraries/model/src/model/Light.h b/libraries/model/src/model/Light.h index 058d4d4741..c091026ba2 100755 --- a/libraries/model/src/model/Light.h +++ b/libraries/model/src/model/Light.h @@ -124,7 +124,7 @@ public: float _intensity{1.0f}; Vec4 _attenuation{0.1f, 1.0f, 0.0f, 0.0f}; Vec4 _spot{0.0f, 0.0f, 0.0f, 0.0f}; - Vec4 _shadow{0.0f}; + //Vec4 _shadow{0.0f}; float _ambientMapNumMips{ 0.0f }; diff --git a/libraries/model/src/model/Light.slh b/libraries/model/src/model/Light.slh index 2b6e55cf7e..888abf5038 100644 --- a/libraries/model/src/model/Light.slh +++ b/libraries/model/src/model/Light.slh @@ -53,7 +53,7 @@ struct Light { vec4 _attenuation; vec4 _spot; - vec4 _shadow; + // vec4 _shadow; vec4 _control; vec4 _volumeGeometry; diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index e6ca901376..1a0a072256 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -118,9 +118,7 @@ void DeferredLightingEffect::init() { // Light Stage and clusters _lightStage = std::make_shared(); - _lightClusters = std::make_shared(); - _lightClusters->updateLightStage(_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::LightPointer lp = _allocatedLights[0]; @@ -146,6 +144,7 @@ void DeferredLightingEffect::addLight(const model::LightPointer& light) { } } + void DeferredLightingEffect::addPointLight(const glm::vec3& position, float radius, const glm::vec3& color, float intensity, float falloffRadius) { addSpotLight(position, radius, color, intensity, falloffRadius); @@ -472,6 +471,7 @@ void PreparePrimaryFramebuffer::run(const SceneContextPointer& sceneContext, con } _primaryFramebuffer->resize(frameSize.x, frameSize.y); + primaryFramebuffer = _primaryFramebuffer; } @@ -508,6 +508,11 @@ void PrepareDeferred::run(const SceneContextPointer& sceneContext, const RenderC // For the rest of the rendering, bind the lighting model batch.setUniformBuffer(LIGHTING_MODEL_BUFFER_SLOT, lightingModel->getParametersBuffer()); }); + + + // Prepare a fresh Light Frame + auto deferredLightingEffect = DependencyManager::get(); + deferredLightingEffect->getLightStage()->_currentFrame.clear(); } diff --git a/libraries/render-utils/src/DeferredLightingEffect.h b/libraries/render-utils/src/DeferredLightingEffect.h index a66a2ed2ed..690d6ce5e0 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.h +++ b/libraries/render-utils/src/DeferredLightingEffect.h @@ -62,7 +62,6 @@ public: void setGlobalLight(const model::LightPointer& light); const LightStagePointer getLightStage() { return _lightStage; } - const LightClustersPointer getLightClusters() { return _lightClusters; } void setShadowMapEnabled(bool enable) { _shadowMapEnabled = enable; }; void setAmbientOcclusionEnabled(bool enable) { _ambientOcclusionEnabled = enable; } @@ -73,8 +72,6 @@ private: LightStagePointer _lightStage; - LightClustersPointer _lightClusters; - bool _shadowMapEnabled{ false }; bool _ambientOcclusionEnabled{ false }; diff --git a/libraries/render-utils/src/LightClusters.cpp b/libraries/render-utils/src/LightClusters.cpp index e98322da4d..97f91657df 100644 --- a/libraries/render-utils/src/LightClusters.cpp +++ b/libraries/render-utils/src/LightClusters.cpp @@ -47,13 +47,36 @@ void LightClusters::updateFrustum(const ViewFrustum& frustum) { void LightClusters::updateLightStage(const LightStagePointer& lightStage) { _lightStage = lightStage; -} - -void LightClusters::updateVisibleLights(const LightStage::LightIndices& visibleLights) { + } + +void LightClusters::updateLightFrame(const LightStage::Frame& lightFrame, bool points, bool spots) { + + // start fresh _visibleLightIndices.clear(); - // _lightClusters->_visibleLightIndices.push_back(0); - _visibleLightIndices = visibleLights; + + // Now gather the lights + // gather lights + auto& srcPointLights = lightFrame._pointLights; + auto& srcSpotLights = lightFrame._spotLights; + int numPointLights = (int) srcPointLights.size(); + // int offsetPointLights = 0; + int numSpotLights = (int) srcSpotLights.size(); + // int offsetSpotLights = numPointLights; + + _visibleLightIndices.resize(numPointLights + numSpotLights + 1); + + _visibleLightIndices[0] = 0; + + if (points && !srcPointLights.empty()) { + memcpy(_visibleLightIndices.data() + (_visibleLightIndices[0] + 1), srcPointLights.data(), srcPointLights.size() * sizeof(int)); + _visibleLightIndices[0] += (int)srcPointLights.size(); + } + if (spots && !srcSpotLights.empty()) { + memcpy(_visibleLightIndices.data() + (_visibleLightIndices[0] + 1), srcSpotLights.data(), srcSpotLights.size() * sizeof(int)); + _visibleLightIndices[0] += (int)srcSpotLights.size(); + } + _lightIndicesBuffer._buffer->setData(_visibleLightIndices.size() * sizeof(int), (const gpu::Byte*) _visibleLightIndices.data()); _lightIndicesBuffer._size = _visibleLightIndices.size() * sizeof(int); } @@ -83,12 +106,9 @@ void LightClusteringPass::run(const render::SceneContextPointer& sceneContext, c auto lightingModel = inputs.get1(); auto surfaceGeometryFramebuffer = inputs.get2(); - bool points = lightingModel->isPointLightEnabled(); - bool spots = lightingModel->isSpotLightEnabled(); - auto deferredLightingEffect = DependencyManager::get(); if (!_lightClusters) { - _lightClusters = deferredLightingEffect->getLightClusters(); + _lightClusters = std::make_shared(); } // first update the Grid with the new frustum @@ -96,28 +116,11 @@ void LightClusteringPass::run(const render::SceneContextPointer& sceneContext, c _lightClusters->updateFrustum(args->getViewFrustum()); } - // Now gather the lights - // gather lights - auto& srcPointLights = deferredLightingEffect->_pointLights; - auto& srcSpotLights = deferredLightingEffect->_spotLights; - int numPointLights = (int) srcPointLights.size(); - int offsetPointLights = 0; - int numSpotLights = (int) srcSpotLights.size(); - int offsetSpotLights = numPointLights; - - std::vector lightIndices(numPointLights + numSpotLights + 1); - lightIndices[0] = 0; - - if (points && !srcPointLights.empty()) { - memcpy(lightIndices.data() + (lightIndices[0] + 1), srcPointLights.data(), srcPointLights.size() * sizeof(int)); - lightIndices[0] += (int)srcPointLights.size(); - } - if (spots && !srcSpotLights.empty()) { - memcpy(lightIndices.data() + (lightIndices[0] + 1), srcSpotLights.data(), srcSpotLights.size() * sizeof(int)); - lightIndices[0] += (int)srcSpotLights.size(); - } - - _lightClusters->updateVisibleLights(lightIndices); + // From the LightStage and the current frame, update the light cluster Grid + auto deferredLightingEffect = DependencyManager::get(); + auto lightStage = deferredLightingEffect->getLightStage(); + _lightClusters->updateLightStage(lightStage); + _lightClusters->updateLightFrame(lightStage->_currentFrame, lightingModel->isPointLightEnabled(), lightingModel->isSpotLightEnabled()); output = _lightClusters; } diff --git a/libraries/render-utils/src/LightClusters.h b/libraries/render-utils/src/LightClusters.h index 0cfaea5ef5..60b4d50ced 100644 --- a/libraries/render-utils/src/LightClusters.h +++ b/libraries/render-utils/src/LightClusters.h @@ -61,9 +61,8 @@ public: void updateLightStage(const LightStagePointer& lightStage); - void updateVisibleLights(const LightStage::LightIndices& visibleLights); - - + void updateLightFrame(const LightStage::Frame& lightFrame, bool points = true, bool spots = true); + ViewFrustum _frustum; LightStagePointer _lightStage; diff --git a/libraries/render-utils/src/LightPayload.cpp b/libraries/render-utils/src/LightPayload.cpp index 8bb9a57145..e8d9e0d5bd 100644 --- a/libraries/render-utils/src/LightPayload.cpp +++ b/libraries/render-utils/src/LightPayload.cpp @@ -35,11 +35,34 @@ namespace render { } LightPayload::LightPayload() : -_light(std::make_shared()) + _light(std::make_shared()) { } -void LightPayload::render(RenderArgs* args) { - DependencyManager::get()->addLight(_light); -} \ No newline at end of file +LightPayload::~LightPayload() { + if (!LightStage::isIndexInvalid(_index)) { + if (_stage) { + _stage->removeLight(_index); + } + } +} + +void LightPayload::render(RenderArgs* args) { + if (!_stage) { + _stage = DependencyManager::get()->getLightStage(); + } + // Do we need to allocate the light in the stage ? + if (LightStage::isIndexInvalid(_index)) { + _index = _stage->addLight(_light); + } + // Need an update ? + if (_needUpdate) { + _stage->updateLightArrayBuffer(_index); + _needUpdate = false; + } + + // FInally, push the light visible in the frame + _stage->_currentFrame.pushLight(_index, _light->getType()); +} + diff --git a/libraries/render-utils/src/LightPayload.h b/libraries/render-utils/src/LightPayload.h index 2f065e4b5b..fba4ff15cb 100644 --- a/libraries/render-utils/src/LightPayload.h +++ b/libraries/render-utils/src/LightPayload.h @@ -14,7 +14,7 @@ #include #include - +#include "LightStage.h" class LightPayload { public: @@ -22,14 +22,18 @@ public: using Pointer = Payload::DataPointer; LightPayload(); + ~LightPayload(); void render(RenderArgs* args); - model::LightPointer editLight() { return _light; } - render::Item::Bound& editBound() { return _bound; } - + model::LightPointer editLight() { _needUpdate = true; return _light; } + render::Item::Bound& editBound() { _needUpdate = true; return _bound; } + protected: model::LightPointer _light; render::Item::Bound _bound; + LightStagePointer _stage; + LightStage::Index _index { LightStage::INVALID_INDEX }; + bool _needUpdate { true }; }; namespace render { diff --git a/libraries/render-utils/src/LightStage.cpp b/libraries/render-utils/src/LightStage.cpp index bcdee5c0a9..8c8c9406e0 100644 --- a/libraries/render-utils/src/LightStage.cpp +++ b/libraries/render-utils/src/LightStage.cpp @@ -123,6 +123,16 @@ LightStage::Index LightStage::addLight(const LightPointer& light) { } } +LightStage::LightPointer LightStage::removeLight(Index index) { + LightPointer removed = _lights.freeElement(index); + + if (removed) { + _lightMap.erase(removed); + _descs[index] = Desc(); + } + return removed; +} + void LightStage::updateLightArrayBuffer(Index lightId) { if (!_lightArrayBuffer) { _lightArrayBuffer = std::make_shared(); diff --git a/libraries/render-utils/src/LightStage.h b/libraries/render-utils/src/LightStage.h index c0632a0ebf..34575596dd 100644 --- a/libraries/render-utils/src/LightStage.h +++ b/libraries/render-utils/src/LightStage.h @@ -27,7 +27,8 @@ class LightStage { public: using Index = render::indexed_container::Index; static const Index INVALID_INDEX { render::indexed_container::INVALID_INDEX }; - + static bool isIndexInvalid(Index index) { return index == INVALID_INDEX; } + using LightPointer = model::LightPointer; using Lights = render::indexed_container::IndexedPointerVector; using LightMap = std::unordered_map; @@ -79,7 +80,8 @@ public: Index findLight(const LightPointer& light) const; Index addLight(const LightPointer& light); - + LightPointer removeLight(Index index); + bool checkLightId(Index index) const { return _lights.checkIndex(index); } Index getNumLights() const { return _lights.getNumElements(); } @@ -107,10 +109,35 @@ public: LightMap _lightMap; Descs _descs; + class Frame { + public: + Frame() {} + + void clear() { _pointLights.clear(); _spotLights.clear(); } + void pushLight(LightStage::Index index, model::Light::Type type) { + switch (type) { + case model::Light::POINT: { pushPointLight(index); break; } + case model::Light::SPOT: { pushSpotLight(index); break; } + default: { break; } + } + } + void pushPointLight(LightStage::Index index) { _pointLights.emplace_back(index); } + void pushSpotLight(LightStage::Index index) { _spotLights.emplace_back(index); } + + LightStage::LightIndices _pointLights; + LightStage::LightIndices _spotLights; + }; + + Frame _currentFrame; + gpu::BufferPointer _lightArrayBuffer; void updateLightArrayBuffer(Index lightId); Shadows _shadows; }; using LightStagePointer = std::shared_ptr; + + + + #endif diff --git a/scripts/developer/utilities/render/lightClustering.qml b/scripts/developer/utilities/render/lightClustering.qml index be252441db..9adb137b0f 100644 --- a/scripts/developer/utilities/render/lightClustering.qml +++ b/scripts/developer/utilities/render/lightClustering.qml @@ -40,6 +40,16 @@ Column { checked: Render.getConfig("LightClustering")["freeze"] onCheckedChanged: { Render.getConfig("LightClustering")["freeze"] = checked } } + CheckBox { + text: "Draw Grid" + checked: Render.getConfig("DebugLightClusters")["doDrawGrid"] + onCheckedChanged: { Render.getConfig("DebugLightClusters")["doDrawGrid"] = checked } + } + CheckBox { + text: "Draw Cluster From Depth" + checked: Render.getConfig("DebugLightClusters")["doDrawClusterFromDepth"] + onCheckedChanged: { Render.getConfig("DebugLightClusters")["doDrawClusterFromDepth"] = checked } + } } } } From efc4406b472f537ec2732aa6d0de21830de691df Mon Sep 17 00:00:00 2001 From: samcake Date: Mon, 12 Sep 2016 19:46:18 -0700 Subject: [PATCH 28/75] Debugging the grid content --- libraries/gpu/src/gpu/Buffer.h | 7 +- libraries/gpu/src/gpu/Format.cpp | 3 +- libraries/gpu/src/gpu/Format.h | 1 + .../render-utils/src/LightClusterGrid.slh | 9 + .../src/LightClusterGrid_shared.slh | 32 ++- libraries/render-utils/src/LightClusters.cpp | 219 +++++++++++++++++- libraries/render-utils/src/LightClusters.h | 22 +- libraries/render-utils/src/LightPayload.cpp | 1 + libraries/render-utils/src/LightStage.cpp | 10 +- .../render-utils/src/RenderDeferredTask.cpp | 4 +- .../src/lightClusters_drawClusterContent.slf | 19 ++ .../src/lightClusters_drawClusterContent.slv | 74 ++++++ 12 files changed, 379 insertions(+), 22 deletions(-) create mode 100644 libraries/render-utils/src/lightClusters_drawClusterContent.slf create mode 100644 libraries/render-utils/src/lightClusters_drawClusterContent.slv diff --git a/libraries/gpu/src/gpu/Buffer.h b/libraries/gpu/src/gpu/Buffer.h index e8e04f471a..2079c60605 100644 --- a/libraries/gpu/src/gpu/Buffer.h +++ b/libraries/gpu/src/gpu/Buffer.h @@ -391,11 +391,14 @@ public: ~StructBuffer() {}; StructBuffer() : gpu::BufferView(makeBuffer()) {} - const T* operator ->() const { return &get(); } + T& edit() { return BufferView::edit(0); } - + const T& get() const { + return BufferView::get(0); + } + const T* operator ->() const { return &get(); } }; }; diff --git a/libraries/gpu/src/gpu/Format.cpp b/libraries/gpu/src/gpu/Format.cpp index 83b2a59a73..2a8185bf94 100644 --- a/libraries/gpu/src/gpu/Format.cpp +++ b/libraries/gpu/src/gpu/Format.cpp @@ -18,6 +18,7 @@ const Element Element::VEC2F_UV{ VEC2, FLOAT, UV }; const Element Element::VEC2F_XY{ VEC2, FLOAT, XY }; const Element Element::VEC3F_XYZ{ VEC3, FLOAT, XYZ }; const Element Element::VEC4F_XYZW{ VEC4, FLOAT, XYZW }; -const Element Element::INDEX_UINT16{ SCALAR, UINT16, INDEX }; +const Element Element::INDEX_UINT16 { SCALAR, UINT16, INDEX }; +const Element Element::INDEX_INT32 { SCALAR, INT32, INDEX }; const Element Element::PART_DRAWCALL{ VEC4, UINT32, PART }; diff --git a/libraries/gpu/src/gpu/Format.h b/libraries/gpu/src/gpu/Format.h index ad630e8e43..13809a41e6 100644 --- a/libraries/gpu/src/gpu/Format.h +++ b/libraries/gpu/src/gpu/Format.h @@ -236,6 +236,7 @@ public: static const Element VEC3F_XYZ; static const Element VEC4F_XYZW; static const Element INDEX_UINT16; + static const Element INDEX_INT32; static const Element PART_DRAWCALL; protected: diff --git a/libraries/render-utils/src/LightClusterGrid.slh b/libraries/render-utils/src/LightClusterGrid.slh index 004339ff34..5b1b765e0f 100644 --- a/libraries/render-utils/src/LightClusterGrid.slh +++ b/libraries/render-utils/src/LightClusterGrid.slh @@ -46,4 +46,13 @@ float projection_getFar(mat4 projection) { // end of hybrid include + +uniform clusterGridBuffer { + int _clusterGridTable[10000]; +}; + +uniform clusterContentBuffer { + int _clusterGridContent[10000]; +}; + <@endif@> diff --git a/libraries/render-utils/src/LightClusterGrid_shared.slh b/libraries/render-utils/src/LightClusterGrid_shared.slh index 5ccba9a786..5577b2e612 100644 --- a/libraries/render-utils/src/LightClusterGrid_shared.slh +++ b/libraries/render-utils/src/LightClusterGrid_shared.slh @@ -17,11 +17,16 @@ vec3 frustumGrid_gridToVolume(vec3 pos, ivec3 dims) { } +float frustumGrid_volumeToGridDepth(float vposZ, ivec3 dims) { + return frustumGrid_depthRampInverse(vposZ) * float(dims.z); +} + vec3 frustumGrid_volumeToGrid(vec3 vpos, ivec3 dims) { vec3 gridPos = vec3(vpos.x, vpos.y, frustumGrid_depthRampInverse(vpos.z)) * vec3(dims); return gridPos; } + vec4 frustumGrid_volumeToClip(vec3 vpos, float rangeNear, float rangeFar) { vec3 ndcPos = vec3(-1.0 + 2.0 * vpos.x, -1.0 + 2.0 * vpos.y, vpos.z); float depth = rangeNear * (1 - ndcPos.z) + rangeFar * (ndcPos.z); @@ -42,6 +47,10 @@ vec3 frustumGrid_volumeToEye(vec3 vpos, mat4 projection, float rangeNear, float return frustumGrid_clipToEye(frustumGrid_volumeToClip(vpos, rangeNear, rangeFar), projection); } +float frustumGrid_eyeToVolumeDepth(float eposZ, float rangeNear, float rangeFar) { + return (-eposZ - rangeNear) / (rangeFar - rangeNear); +} + vec3 frustumGrid_eyeToVolume(vec3 epos, mat4 projection, float rangeNear, float rangeFar) { vec4 clipPos = vec4(epos.x * projection[0][0] + epos.z * projection[2][0], @@ -57,7 +66,7 @@ vec3 frustumGrid_eyeToVolume(vec3 epos, mat4 projection, float rangeNear, float int frustumGrid_numClusters() { - return frustumGrid.dims.x * frustumGrid.dims.y * (frustumGrid.dims.z); + return frustumGrid.dims.x * frustumGrid.dims.y * (frustumGrid.dims.z + 1); } vec3 frustumGrid_clusterPosToEye(ivec3 clusterPos, vec3 offset) { @@ -73,6 +82,27 @@ vec3 frustumGrid_clusterPosToEye(ivec3 clusterPos, vec3 offset) { } +int frustumGrid_eyeDepthToClusterLayer(float eyeZ) { + if ((eyeZ > -frustumGrid.frustumNear) || (eyeZ < -frustumGrid.frustumFar)) { + return -1; + } + + if (eyeZ > -frustumGrid.rangeNear) { + return -1; + } + + float volumeZ = frustumGrid_eyeToVolumeDepth(eyeZ, frustumGrid.rangeNear, frustumGrid.rangeFar); + + float gridZ = frustumGrid_volumeToGridDepth(volumeZ, frustumGrid.dims); + + if (gridZ >= frustumGrid.dims.z) { + gridZ = frustumGrid.dims.z; + } + + + return int(gridZ); +} + ivec3 frustumGrid_eyeToClusterPos(vec3 eyePos) { if ((eyePos.z > -frustumGrid.frustumNear) || (eyePos.z < -frustumGrid.frustumFar)) { return ivec3(-1); diff --git a/libraries/render-utils/src/LightClusters.cpp b/libraries/render-utils/src/LightClusters.cpp index 97f91657df..ff9362eb3e 100644 --- a/libraries/render-utils/src/LightClusters.cpp +++ b/libraries/render-utils/src/LightClusters.cpp @@ -21,6 +21,10 @@ //#include "lightClusters_drawClusterFromDepth_vert.h" #include "lightClusters_drawClusterFromDepth_frag.h" + +#include "lightClusters_drawClusterContent_vert.h" +#include "lightClusters_drawClusterContent_frag.h" + enum LightClusterGridShader_MapSlot { DEFERRED_BUFFER_LINEAR_DEPTH_UNIT = 0, }; @@ -31,14 +35,32 @@ enum LightClusterGridShader_BufferSlot { CAMERA_CORRECTION_BUFFER_SLOT, LIGHT_GPU_SLOT = render::ShapePipeline::Slot::LIGHT, LIGHT_INDEX_GPU_SLOT, + + LIGHT_CLUSTER_GRID_CLUSTER_GRID_SLOT, + LIGHT_CLUSTER_GRID_CLUSTER_CONTENT_SLOT, }; #include "DeferredLightingEffect.h" LightClusters::LightClusters() : -_lightIndicesBuffer(std::make_shared()) { + _lightIndicesBuffer(std::make_shared()), + _clusterGridBuffer(std::make_shared(), gpu::Element::INDEX_INT32), + _clusterContentBuffer(std::make_shared(), gpu::Element::INDEX_INT32) { + setDimensions(_frustumGridBuffer->dims, 10000); } +void LightClusters::setDimensions(glm::uvec3 gridDims, uint32_t listBudget) { + _frustumGridBuffer.edit().dims = gridDims; + + _numClusters = _frustumGridBuffer.edit().frustumGrid_numClusters(); + + _clusterGridBuffer._size = _clusterGridBuffer._buffer->resize(_numClusters * sizeof(uint32_t)); + _clusterContentBuffer._size = _clusterContentBuffer._buffer->resize(listBudget * sizeof(uint32_t)); + _clusterGrid.resize(_numClusters, EMPTY_CLUSTER); + _clusterContent.resize(listBudget, INVALID_LIGHT); +} + + void LightClusters::updateFrustum(const ViewFrustum& frustum) { _frustum = frustum; @@ -51,23 +73,23 @@ void LightClusters::updateLightStage(const LightStagePointer& lightStage) { } void LightClusters::updateLightFrame(const LightStage::Frame& lightFrame, bool points, bool spots) { - + // start fresh _visibleLightIndices.clear(); - + // Now gather the lights // gather lights auto& srcPointLights = lightFrame._pointLights; auto& srcSpotLights = lightFrame._spotLights; - int numPointLights = (int) srcPointLights.size(); - // int offsetPointLights = 0; - int numSpotLights = (int) srcSpotLights.size(); - // int offsetSpotLights = numPointLights; - + int numPointLights = (int)srcPointLights.size(); + // int offsetPointLights = 0; + int numSpotLights = (int)srcSpotLights.size(); + // int offsetSpotLights = numPointLights; + _visibleLightIndices.resize(numPointLights + numSpotLights + 1); - + _visibleLightIndices[0] = 0; - + if (points && !srcPointLights.empty()) { memcpy(_visibleLightIndices.data() + (_visibleLightIndices[0] + 1), srcPointLights.data(), srcPointLights.size() * sizeof(int)); _visibleLightIndices[0] += (int)srcPointLights.size(); @@ -76,11 +98,144 @@ void LightClusters::updateLightFrame(const LightStage::Frame& lightFrame, bool p memcpy(_visibleLightIndices.data() + (_visibleLightIndices[0] + 1), srcSpotLights.data(), srcSpotLights.size() * sizeof(int)); _visibleLightIndices[0] += (int)srcSpotLights.size(); } - + _lightIndicesBuffer._buffer->setData(_visibleLightIndices.size() * sizeof(int), (const gpu::Byte*) _visibleLightIndices.data()); _lightIndicesBuffer._size = _visibleLightIndices.size() * sizeof(int); } +void LightClusters::updateClusters() { + // Clean up last info + std::vector< std::vector< uint32_t > > clusterGrid(_numClusters); + + _clusterGrid.resize(_numClusters, EMPTY_CLUSTER); + uint32_t maxNumIndices = _clusterContent.size(); + _clusterContent.resize(maxNumIndices, INVALID_LIGHT); + + auto theFrustumGrid(_frustumGridBuffer.get()); + + glm::ivec3 gridPosToOffset(1, theFrustumGrid.dims.x, theFrustumGrid.dims.x * theFrustumGrid.dims.y); + + uint32_t numClusterTouched = 0; + for (size_t lightNum = 1; lightNum < _visibleLightIndices.size(); ++lightNum) { + auto lightId = _visibleLightIndices[lightNum]; + auto light = _lightStage->getLight(lightId); + if (!light) + continue; + + auto worldOri = light->getPosition(); + auto radius = light->getMaximumRadius(); + + // Bring into frustum eye space + auto eyeOri = theFrustumGrid.frustumGrid_worldToEye(glm::vec4(worldOri, 1.0f)); + + // Remove light that slipped through and is not in the z range + float eyeZMax = eyeOri.z - radius; + if (eyeZMax > -theFrustumGrid.rangeNear) { + continue; + } + float eyeZMin = eyeOri.z + radius; + if (eyeZMin < -theFrustumGrid.rangeFar) { + continue; + } + + // Get z slices + int zMin = theFrustumGrid.frustumGrid_eyeDepthToClusterLayer(eyeZMin); + int zMax = theFrustumGrid.frustumGrid_eyeDepthToClusterLayer(eyeZMax); + // That should never happen + if (zMin == -1 && zMax == -1) { + continue; + } + + + // + float eyeOriLen2 = glm::length2(eyeOri); + + // CLamp the z range + zMin = std::max(0, zMin); + + + + // find 2D corners of the sphere in grid + int xMin { 0 }; + int xMax { theFrustumGrid.dims.x - 1 }; + int yMin { 0 }; + int yMax { theFrustumGrid.dims.y - 1 }; + + float radius2 = radius * radius; + auto eyeOriH = eyeOri; + auto eyeOriV = eyeOri; + + eyeOriH.y = 0.0f; + eyeOriV.x = 0.0f; + + float eyeOriLen2H = glm::length2(eyeOriH); + float eyeOriLen2V = glm::length2(eyeOriV); + + if ((eyeOriLen2H > radius2) && (eyeOriLen2V > radius2)) { + float eyeOriLenH = sqrt(eyeOriLen2H); + float eyeOriLenV = sqrt(eyeOriLen2V); + + auto eyeOriDirH = glm::vec3(eyeOriH) / eyeOriLenH; + auto eyeOriDirV = glm::vec3(eyeOriV) / eyeOriLenV; + + + + float eyeToTangentCircleLenH = sqrt(eyeOriLen2H - radius2); + float eyeToTangentCircleLenV = sqrt(eyeOriLen2V - radius2); + + float eyeToTangentCircleTanH = radius / eyeToTangentCircleLenH; + float eyeToTangentCircleTanV = radius / eyeToTangentCircleLenV; + + float eyeToTangentCircleCosH = eyeToTangentCircleLenH / eyeOriLenH; + float eyeToTangentCircleCosV = eyeToTangentCircleLenV / eyeOriLenV; + + float eyeToTangentCircleSinH = radius / eyeOriLenH; + float eyeToTangentCircleSinV = radius / eyeOriLenV; + + + // rotate the eyeToOriDir (H & V) in both directions + glm::vec3 leftDir(eyeOriDirH.x * eyeToTangentCircleCosH - eyeOriDirH.z * eyeToTangentCircleSinH, 0.0f, eyeOriDirH.x * eyeToTangentCircleSinH + eyeOriDirH.z * eyeToTangentCircleCosH); + glm::vec3 rightDir(eyeOriDirH.x * eyeToTangentCircleCosH + eyeOriDirH.z * eyeToTangentCircleSinH, 0.0f, eyeOriDirH.x * -eyeToTangentCircleSinH + eyeOriDirH.z * eyeToTangentCircleCosH); + glm::vec3 bottomDir(0.0f, eyeOriDirV.y * eyeToTangentCircleCosV - eyeOriDirV.z * eyeToTangentCircleSinV, eyeOriDirV.y * eyeToTangentCircleSinV + eyeOriDirV.z * eyeToTangentCircleCosV); + glm::vec3 topDir(0.0f, eyeOriDirV.y * eyeToTangentCircleCosV + eyeOriDirV.z * eyeToTangentCircleSinV, eyeOriDirV.y * -eyeToTangentCircleSinV + eyeOriDirV.z * eyeToTangentCircleCosV); + + } + + // now voxelize + for (auto z = zMin; z <= zMax; z++) { + for (auto y = yMin; y <= yMax; y++) { + for (auto x = xMin; x <= xMax; x++) { + auto index = x + gridPosToOffset.y * y + gridPosToOffset.z * z; + clusterGrid[index].emplace_back(lightId); + numClusterTouched++; + } + } + } + } + + // Lights have been gathered now reexpress in terms of 2 sequential buffers + + uint16_t indexOffset = 0; + for (int i = 0; i < clusterGrid.size(); i++) { + auto& cluster = clusterGrid[i]; + uint16_t numLights = ((uint16_t)cluster.size()); + uint16_t offset = indexOffset; + + _clusterGrid[i] = (uint32_t)((numLights << 16) | offset); + + if (numLights) { + memcpy(_clusterContent.data() + indexOffset, cluster.data(), numLights * sizeof(uint32_t)); + } + + indexOffset += numLights; + } + + // update the buffers + _clusterGridBuffer._buffer->setData(_clusterGridBuffer._size, (gpu::Byte*) _clusterGrid.data()); + _clusterContentBuffer._buffer->setSubData(0, indexOffset * sizeof(uint32_t), (gpu::Byte*) _clusterContent.data()); +} + + LightClusteringPass::LightClusteringPass() { } @@ -122,6 +277,8 @@ void LightClusteringPass::run(const render::SceneContextPointer& sceneContext, c _lightClusters->updateLightStage(lightStage); _lightClusters->updateLightFrame(lightStage->_currentFrame, lightingModel->isPointLightEnabled(), lightingModel->isSpotLightEnabled()); + _lightClusters->updateClusters(); + output = _lightClusters; } @@ -190,6 +347,35 @@ const gpu::PipelinePointer DebugLightClusters::getDrawClusterFromDepthPipeline() return _drawClusterFromDepth; } +const gpu::PipelinePointer DebugLightClusters::getDrawClusterContentPipeline() { + if (!_drawClusterContent) { + auto vs = gpu::Shader::createVertex(std::string(lightClusters_drawClusterContent_vert)); + auto ps = gpu::Shader::createPixel(std::string(lightClusters_drawClusterContent_frag)); + gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps); + + gpu::Shader::BindingSet slotBindings; + slotBindings.insert(gpu::Shader::Binding(std::string("frustumGridBuffer"), LIGHT_CLUSTER_GRID_FRUSTUM_GRID_SLOT)); + slotBindings.insert(gpu::Shader::Binding(std::string("clusterGridBuffer"), LIGHT_CLUSTER_GRID_CLUSTER_GRID_SLOT)); + slotBindings.insert(gpu::Shader::Binding(std::string("clusterContentBuffer"), LIGHT_CLUSTER_GRID_CLUSTER_CONTENT_SLOT)); + + + gpu::Shader::makeProgram(*program, slotBindings); + + + auto state = std::make_shared(); + + state->setDepthTest(true, false, gpu::LESS_EQUAL); + + // Blend on transparent + state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA); + + // Good to go add the brand new pipeline + _drawClusterContent = gpu::Pipeline::create(program, state); + } + return _drawClusterContent; +} + + void DebugLightClusters::run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext, const Inputs& inputs) { auto deferredTransform = inputs.get0(); auto deferredFramebuffer = inputs.get1(); @@ -232,6 +418,17 @@ void DebugLightClusters::run(const render::SceneContextPointer& sceneContext, co batch.setResourceTexture(DEFERRED_BUFFER_LINEAR_DEPTH_UNIT, nullptr); batch.setUniformBuffer(DEFERRED_FRAME_TRANSFORM_BUFFER_SLOT, nullptr); } + + if (doDrawContent) { + // bind the one gpu::Pipeline we need + batch.setPipeline(getDrawClusterContentPipeline()); + batch.setUniformBuffer(LIGHT_CLUSTER_GRID_CLUSTER_GRID_SLOT, lightClusters->_clusterGridBuffer); + batch.setUniformBuffer(LIGHT_CLUSTER_GRID_CLUSTER_CONTENT_SLOT, lightClusters->_clusterContentBuffer); + + auto dims = lightClusters->_frustumGridBuffer->dims; + glm::ivec3 summedDims(dims.x*dims.y * dims.z, dims.x*dims.y, dims.x); + batch.drawInstanced(summedDims.x, gpu::LINES, 24, 0); + } if (doDrawGrid) { // bind the one gpu::Pipeline we need diff --git a/libraries/render-utils/src/LightClusters.h b/libraries/render-utils/src/LightClusters.h index 60b4d50ced..9930eda731 100644 --- a/libraries/render-utils/src/LightClusters.h +++ b/libraries/render-utils/src/LightClusters.h @@ -57,12 +57,16 @@ public: LightClusters(); + void setDimensions(glm::uvec3 gridDims, uint32_t listBudget); + void updateFrustum(const ViewFrustum& frustum); void updateLightStage(const LightStagePointer& lightStage); void updateLightFrame(const LightStage::Frame& lightFrame, bool points = true, bool spots = true); - + + void updateClusters(); + ViewFrustum _frustum; LightStagePointer _lightStage; @@ -72,8 +76,17 @@ public: gpu::StructBuffer _frustumGridBuffer; LightStage::LightIndices _visibleLightIndices; - gpu::BufferView _lightIndicesBuffer; + + uint32_t _numClusters { 0 }; + + const uint32_t EMPTY_CLUSTER { 0x0000FFFF }; + const uint32_t INVALID_LIGHT { 0xFFFFFFFF }; + + std::vector _clusterGrid; + std::vector _clusterContent; + gpu::BufferView _clusterGridBuffer; + gpu::BufferView _clusterContentBuffer; }; using LightClustersPointer = std::shared_ptr; @@ -162,10 +175,13 @@ protected: gpu::BufferPointer _gridBuffer; gpu::PipelinePointer _drawClusterGrid; gpu::PipelinePointer _drawClusterFromDepth; + gpu::PipelinePointer _drawClusterContent; const gpu::PipelinePointer getDrawClusterGridPipeline(); const gpu::PipelinePointer getDrawClusterFromDepthPipeline(); + const gpu::PipelinePointer getDrawClusterContentPipeline(); bool doDrawGrid{ false }; - bool doDrawClusterFromDepth{ false }; + bool doDrawClusterFromDepth { false }; + bool doDrawContent { true }; }; #endif diff --git a/libraries/render-utils/src/LightPayload.cpp b/libraries/render-utils/src/LightPayload.cpp index e8d9e0d5bd..8f7b893f6a 100644 --- a/libraries/render-utils/src/LightPayload.cpp +++ b/libraries/render-utils/src/LightPayload.cpp @@ -55,6 +55,7 @@ void LightPayload::render(RenderArgs* args) { // Do we need to allocate the light in the stage ? if (LightStage::isIndexInvalid(_index)) { _index = _stage->addLight(_light); + _needUpdate = false; } // Need an update ? if (_needUpdate) { diff --git a/libraries/render-utils/src/LightStage.cpp b/libraries/render-utils/src/LightStage.cpp index 8c8c9406e0..357e7f46f7 100644 --- a/libraries/render-utils/src/LightStage.cpp +++ b/libraries/render-utils/src/LightStage.cpp @@ -146,8 +146,12 @@ void LightStage::updateLightArrayBuffer(Index lightId) { } // lightArray is big enough so we can remap - auto& light = _lights._elements[lightId]; - auto lightSchema = light->getSchemaBuffer().get(); - _lightArrayBuffer->setSubData(lightId, lightSchema); + auto light = _lights._elements[lightId]; + if (light) { + auto lightSchema = light->getSchemaBuffer().get(); + _lightArrayBuffer->setSubData(lightId, lightSchema); + } else { + // this should not happen ? + } } diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index c959743b57..d8f3b325f1 100755 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -192,7 +192,9 @@ RenderDeferredTask::RenderDeferredTask(CullFunctor cullFunctor) { const auto debugFramebuffers = render::Varying(DebugDeferredBuffer::Inputs(deferredFramebuffer, linearDepthTarget, surfaceGeometryFramebuffer, ambientOcclusionFramebuffer)); addJob("DebugDeferredBuffer", debugFramebuffers); - addJob("DebugScattering", deferredLightingInputs); + const auto debugSubsurfaceScatteringInputs = DebugSubsurfaceScattering::Inputs(deferredFrameTransform, deferredFramebuffer, lightingModel, + surfaceGeometryFramebuffer, ambientOcclusionFramebuffer, scatteringResource).hasVarying(); + addJob("DebugScattering", debugSubsurfaceScatteringInputs); const auto debugAmbientOcclusionInputs = DebugAmbientOcclusion::Inputs(deferredFrameTransform, deferredFramebuffer, linearDepthTarget, ambientOcclusionUniforms).hasVarying(); addJob("DebugAmbientOcclusion", debugAmbientOcclusionInputs); diff --git a/libraries/render-utils/src/lightClusters_drawClusterContent.slf b/libraries/render-utils/src/lightClusters_drawClusterContent.slf new file mode 100644 index 0000000000..b31479554f --- /dev/null +++ b/libraries/render-utils/src/lightClusters_drawClusterContent.slf @@ -0,0 +1,19 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// lightClusters_drawClusterContent.slf +// +// Created by Sam Gateau on 9/8/2016. +// Copyright 2015 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 +// + +in vec4 varColor; +out vec4 outFragColor; + + +void main(void) { + outFragColor = varColor; +} diff --git a/libraries/render-utils/src/lightClusters_drawClusterContent.slv b/libraries/render-utils/src/lightClusters_drawClusterContent.slv new file mode 100644 index 0000000000..1e4246da1c --- /dev/null +++ b/libraries/render-utils/src/lightClusters_drawClusterContent.slv @@ -0,0 +1,74 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// lightClusters_drawClusterContent.slv +// Vertex shader +// +// Created by Sam Gateau on 9/8/2016 +// Copyright 2015 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 gpu/Transform.slh@> +<$declareStandardTransform()$> + +<@include LightClusterGrid.slh@> + +<@include gpu/Color.slh@> +<$declareColorWheel()$> + + + + +out vec4 varColor; + + +void main(void) { + const vec4 UNIT_BOX[8] = vec4[8]( + vec4(0.0, 0.0, 0.0, 1.0), + vec4(1.0, 0.0, 0.0, 1.0), + vec4(0.0, 1.0, 0.0, 1.0), + vec4(1.0, 1.0, 0.0, 1.0), + vec4(0.0, 0.0, 1.0, 1.0), + vec4(1.0, 0.0, 1.0, 1.0), + vec4(0.0, 1.0, 1.0, 1.0), + vec4(1.0, 1.0, 1.0, 1.0) + ); + const int UNIT_BOX_LINE_INDICES[24] = int[24]( + 0, 1, + 1, 3, + 3, 2, + 2, 0, + 4, 5, + 5, 7, + 7, 6, + 6, 4, + 2, 6, + 3, 7, + 0, 4, + 1, 5 + ); + vec4 pos = UNIT_BOX[UNIT_BOX_LINE_INDICES[gl_VertexID]]; + + ivec3 dims = frustumGrid.dims.xyz; + + ivec3 summedDims = ivec3(dims.x * dims.y, dims.x, 1); + + int layer = gl_InstanceID / summedDims.x; + int offsetInLayer = gl_InstanceID % summedDims.x; + ivec3 clusterPos = ivec3(offsetInLayer % summedDims.y, offsetInLayer / summedDims.y, layer); + + + vec3 eyePos = frustumGrid_clusterPosToEye(clusterPos, vec3(0.05) + 0.9 * pos.xyz); + vec4 worldPos = frustumGrid_eyeToWorld(vec4(eyePos.xyz, 1.0)); + + + // standard transform + TransformCamera cam = getTransformCamera(); + <$transformWorldToClipPos(cam, worldPos, gl_Position)$> + + varColor = vec4(colorWheel(fract(float(gl_InstanceID) / float(frustumGrid_numClusters()))), 0.9); +} \ No newline at end of file From e9bf19840c0d5bf3a6399eb869f3e796a628b3d7 Mon Sep 17 00:00:00 2001 From: samcake Date: Tue, 13 Sep 2016 08:58:07 -0700 Subject: [PATCH 29/75] minor fixes on mac --- libraries/render-utils/src/LightClusterGrid.slh | 8 ++++---- .../render-utils/src/lightClusters_drawClusterContent.slv | 6 ++++++ 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/libraries/render-utils/src/LightClusterGrid.slh b/libraries/render-utils/src/LightClusterGrid.slh index 5b1b765e0f..5287695b10 100644 --- a/libraries/render-utils/src/LightClusterGrid.slh +++ b/libraries/render-utils/src/LightClusterGrid.slh @@ -47,12 +47,12 @@ float projection_getFar(mat4 projection) { // end of hybrid include -uniform clusterGridBuffer { - int _clusterGridTable[10000]; +layout (std140) uniform clusterGridBuffer { + int _clusterGridTable[4096]; }; -uniform clusterContentBuffer { - int _clusterGridContent[10000]; +layout (std140) uniform clusterContentBuffer { + int _clusterGridContent[4096]; }; <@endif@> diff --git a/libraries/render-utils/src/lightClusters_drawClusterContent.slv b/libraries/render-utils/src/lightClusters_drawClusterContent.slv index 1e4246da1c..a971bb5d2c 100644 --- a/libraries/render-utils/src/lightClusters_drawClusterContent.slv +++ b/libraries/render-utils/src/lightClusters_drawClusterContent.slv @@ -53,6 +53,12 @@ void main(void) { ); vec4 pos = UNIT_BOX[UNIT_BOX_LINE_INDICES[gl_VertexID]]; + int clusterDesc = _clusterGridTable[gl_InstanceID]; + int numLights = 0xFFFF & (clusterDesc >> 16); + + if (numLights <= 0) { + return; + } ivec3 dims = frustumGrid.dims.xyz; ivec3 summedDims = ivec3(dims.x * dims.y, dims.x, 1); From e8c2dc10f1ca1812514dbd320e0e002066c4cb3b Mon Sep 17 00:00:00 2001 From: samcake Date: Tue, 13 Sep 2016 14:59:23 -0700 Subject: [PATCH 30/75] best state for now --- .../src/gpu/gl45/GL45BackendTexture.cpp | 2 +- libraries/gpu/src/gpu/Batch.h | 4 +- .../src/DeferredLightingEffect.cpp | 15 +++++- .../render-utils/src/LightClusterGrid.slh | 24 ++++++++-- .../src/LightClusterGrid_shared.slh | 3 +- libraries/render-utils/src/LightClusters.cpp | 46 ++++++++++++++++--- libraries/render-utils/src/LightClusters.h | 19 ++++++-- .../src/lightClusters_drawClusterContent.slv | 20 +++----- .../lightClusters_drawClusterFromDepth.slf | 10 +++- .../render-utils/src/local_lights_shading.slf | 46 +++++++++++++++++-- .../utilities/render/lightClustering.qml | 30 +++++++++++- 11 files changed, 180 insertions(+), 39 deletions(-) diff --git a/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp b/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp index b511ed7811..3c15194d0f 100644 --- a/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp +++ b/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp @@ -24,7 +24,7 @@ using namespace gpu; using namespace gpu::gl; using namespace gpu::gl45; -#define SPARSE_TEXTURES 1 +#define SPARSE_TEXTURES 0 // Allocate 1 MB of buffer space for paged transfers #define DEFAULT_PAGE_BUFFER_SIZE (1024*1024) diff --git a/libraries/gpu/src/gpu/Batch.h b/libraries/gpu/src/gpu/Batch.h index 8a52eef4ea..f2dbe62b39 100644 --- a/libraries/gpu/src/gpu/Batch.h +++ b/libraries/gpu/src/gpu/Batch.h @@ -32,11 +32,11 @@ namespace gpu { enum ReservedSlot { #ifdef GPU_SSBO_DRAW_CALL_INFO - TRANSFORM_OBJECT_SLOT = 6, + TRANSFORM_OBJECT_SLOT = 14, #else TRANSFORM_OBJECT_SLOT = 31, #endif - TRANSFORM_CAMERA_SLOT = 7, + TRANSFORM_CAMERA_SLOT = 15, }; // The named batch data provides a mechanism for accumulating data into buffers over the course diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index 1a0a072256..d6cf9f9408 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -73,6 +73,10 @@ enum DeferredShader_BufferSlot { LIGHTING_MODEL_BUFFER_SLOT = render::ShapePipeline::Slot::LIGHTING_MODEL, LIGHT_GPU_SLOT = render::ShapePipeline::Slot::LIGHT, LIGHT_INDEX_GPU_SLOT, + LIGHT_CLUSTER_GRID_FRUSTUM_GRID_SLOT, + LIGHT_CLUSTER_GRID_CLUSTER_GRID_SLOT, + LIGHT_CLUSTER_GRID_CLUSTER_CONTENT_SLOT, + }; static void loadLightProgram(const char* vertSource, const char* fragSource, bool lightVolume, gpu::PipelinePointer& program, LightLocationsPtr& locations); @@ -218,7 +222,11 @@ static gpu::ShaderPointer makeLightProgram(const char* vertSource, const char* f slotBindings.insert(gpu::Shader::Binding(std::string("subsurfaceScatteringParametersBuffer"), SCATTERING_PARAMETERS_BUFFER_SLOT)); slotBindings.insert(gpu::Shader::Binding(std::string("lightBuffer"), LIGHT_GPU_SLOT)); slotBindings.insert(gpu::Shader::Binding(std::string("lightIndexBuffer"), LIGHT_INDEX_GPU_SLOT)); - + + + slotBindings.insert(gpu::Shader::Binding(std::string("frustumGridBuffer"), LIGHT_CLUSTER_GRID_FRUSTUM_GRID_SLOT)); + slotBindings.insert(gpu::Shader::Binding(std::string("clusterGridBuffer"), LIGHT_CLUSTER_GRID_CLUSTER_GRID_SLOT)); + slotBindings.insert(gpu::Shader::Binding(std::string("clusterContentBuffer"), LIGHT_CLUSTER_GRID_CLUSTER_CONTENT_SLOT)); gpu::Shader::makeProgram(*program, slotBindings); @@ -716,6 +724,11 @@ void RenderDeferredLocals::run(const render::SceneContextPointer& sceneContext, batch.setUniformBuffer(deferredLightingEffect->_localLightLocations->lightIndexBufferUnit, lightClusters->_lightIndicesBuffer); + batch.setUniformBuffer(LIGHT_CLUSTER_GRID_FRUSTUM_GRID_SLOT, lightClusters->_frustumGridBuffer); + batch.setUniformBuffer(LIGHT_CLUSTER_GRID_CLUSTER_GRID_SLOT, lightClusters->_clusterGridBuffer); + batch.setUniformBuffer(LIGHT_CLUSTER_GRID_CLUSTER_CONTENT_SLOT, lightClusters->_clusterContentBuffer); + + // before we get to the real lighting, let s try to cull down the number of pixels if (false) {/* if (numPointLights > 0) { diff --git a/libraries/render-utils/src/LightClusterGrid.slh b/libraries/render-utils/src/LightClusterGrid.slh index 5287695b10..c70d0d2c6b 100644 --- a/libraries/render-utils/src/LightClusterGrid.slh +++ b/libraries/render-utils/src/LightClusterGrid.slh @@ -47,12 +47,30 @@ float projection_getFar(mat4 projection) { // end of hybrid include -layout (std140) uniform clusterGridBuffer { +uniform clusterGridBuffer { int _clusterGridTable[4096]; }; -layout (std140) uniform clusterContentBuffer { - int _clusterGridContent[4096]; +uniform clusterContentBuffer { + int _clusterGridContent[10000]; }; +int clusterGrid_clusterToIndex(ivec3 pos) { + return pos.x + (pos.y + pos.z * frustumGrid.dims.y) * frustumGrid.dims.x; +} +ivec3 clusterGrid_indexToCluster(int index) { + ivec3 summedDims = ivec3(frustumGrid.dims.x * frustumGrid.dims.y, frustumGrid.dims.x, 1); + int layer = index / summedDims.x; + int offsetInLayer = index % summedDims.x; + ivec3 clusterPos = ivec3(offsetInLayer % summedDims.y, offsetInLayer / summedDims.y, layer); + return clusterPos; +} + +ivec2 clusterGrid_getCluster(int index) { + int clusterDesc = _clusterGridTable[index]; + int numLights = 0xFFFF & (clusterDesc >> 16); + int contentOffset = 0xFFFF & (clusterDesc); + return ivec2(numLights, contentOffset); +} + <@endif@> diff --git a/libraries/render-utils/src/LightClusterGrid_shared.slh b/libraries/render-utils/src/LightClusterGrid_shared.slh index 5577b2e612..4ce469deba 100644 --- a/libraries/render-utils/src/LightClusterGrid_shared.slh +++ b/libraries/render-utils/src/LightClusterGrid_shared.slh @@ -1,5 +1,4 @@ // glsl / C++ compatible source as interface for FrustrumGrid - float frustumGrid_depthRamp(float linear) { // return linear; return linear * linear; @@ -132,6 +131,8 @@ vec4 frustumGrid_worldToEye(vec4 worldPos) { return frustumGrid.worldToEyeMat * worldPos; } + + // <@if 1@> // Trigger Scribe include // <@endif@> End C++ compatible \ No newline at end of file diff --git a/libraries/render-utils/src/LightClusters.cpp b/libraries/render-utils/src/LightClusters.cpp index ff9362eb3e..a2feb2e471 100644 --- a/libraries/render-utils/src/LightClusters.cpp +++ b/libraries/render-utils/src/LightClusters.cpp @@ -194,10 +194,27 @@ void LightClusters::updateClusters() { // rotate the eyeToOriDir (H & V) in both directions - glm::vec3 leftDir(eyeOriDirH.x * eyeToTangentCircleCosH - eyeOriDirH.z * eyeToTangentCircleSinH, 0.0f, eyeOriDirH.x * eyeToTangentCircleSinH + eyeOriDirH.z * eyeToTangentCircleCosH); - glm::vec3 rightDir(eyeOriDirH.x * eyeToTangentCircleCosH + eyeOriDirH.z * eyeToTangentCircleSinH, 0.0f, eyeOriDirH.x * -eyeToTangentCircleSinH + eyeOriDirH.z * eyeToTangentCircleCosH); - glm::vec3 bottomDir(0.0f, eyeOriDirV.y * eyeToTangentCircleCosV - eyeOriDirV.z * eyeToTangentCircleSinV, eyeOriDirV.y * eyeToTangentCircleSinV + eyeOriDirV.z * eyeToTangentCircleCosV); - glm::vec3 topDir(0.0f, eyeOriDirV.y * eyeToTangentCircleCosV + eyeOriDirV.z * eyeToTangentCircleSinV, eyeOriDirV.y * -eyeToTangentCircleSinV + eyeOriDirV.z * eyeToTangentCircleCosV); + glm::vec3 leftDir(eyeOriDirH.x * eyeToTangentCircleCosH + eyeOriDirH.z * eyeToTangentCircleSinH, 0.0f, eyeOriDirH.x * -eyeToTangentCircleSinH + eyeOriDirH.z * eyeToTangentCircleCosH); + glm::vec3 rightDir(eyeOriDirH.x * eyeToTangentCircleCosH - eyeOriDirH.z * eyeToTangentCircleSinH, 0.0f, eyeOriDirH.x * eyeToTangentCircleSinH + eyeOriDirH.z * eyeToTangentCircleCosH); + glm::vec3 bottomDir(0.0f, eyeOriDirV.y * eyeToTangentCircleCosV + eyeOriDirV.z * eyeToTangentCircleSinV, eyeOriDirV.y * -eyeToTangentCircleSinV + eyeOriDirV.z * eyeToTangentCircleCosV); + glm::vec3 topDir(0.0f, eyeOriDirV.y * eyeToTangentCircleCosV - eyeOriDirV.z * eyeToTangentCircleSinV, eyeOriDirV.y * eyeToTangentCircleSinV + eyeOriDirV.z * eyeToTangentCircleCosV); + + + glm::vec3 leftPosAtNear = leftDir * theFrustumGrid.rangeNear * 2.0f; + glm::vec3 rightPosAtNear = rightDir * theFrustumGrid.rangeNear * 2.0f; + glm::vec3 bottomPosAtNear = bottomDir * theFrustumGrid.rangeNear * 2.0f; + glm::vec3 topPosAtNear = topDir * theFrustumGrid.rangeNear * 2.0f; + + auto lc = theFrustumGrid.frustumGrid_eyeToClusterPos(leftPosAtNear); + auto rc = theFrustumGrid.frustumGrid_eyeToClusterPos(rightPosAtNear); + auto bc = theFrustumGrid.frustumGrid_eyeToClusterPos(bottomPosAtNear); + auto tc = theFrustumGrid.frustumGrid_eyeToClusterPos(topPosAtNear); + + xMin = std::max(0, lc.x); + xMax = std::max(0, std::min(rc.x, xMax)); + yMin = std::max(0, bc.y); + yMax = std::max(0, std::min(tc.y, yMax)); + } @@ -249,6 +266,16 @@ void LightClusteringPass::configure(const Config& config) { if (_lightClusters->_frustumGridBuffer->rangeFar != config.rangeFar) { _lightClusters->_frustumGridBuffer.edit().rangeFar = config.rangeFar; } + + ivec3 configDimensions; + configDimensions.x = std::max(0, std::min(16, config.dimX)); + configDimensions.y = std::max(0, std::min(16, config.dimY)); + configDimensions.z = std::max(0, std::min(15, config.dimZ)); + + auto& dims = _lightClusters->_frustumGridBuffer->dims; + if ((dims.x != configDimensions.x) || (dims.y != configDimensions.y) || (dims.z != configDimensions.z)) { + _lightClusters->setDimensions(configDimensions, 10000); + } } _freeze = config.freeze; @@ -290,6 +317,7 @@ DebugLightClusters::DebugLightClusters() { void DebugLightClusters::configure(const Config& config) { doDrawGrid = config.doDrawGrid; doDrawClusterFromDepth = config.doDrawClusterFromDepth; + doDrawContent = config.doDrawContent; } @@ -301,6 +329,9 @@ const gpu::PipelinePointer DebugLightClusters::getDrawClusterGridPipeline() { gpu::Shader::BindingSet slotBindings; slotBindings.insert(gpu::Shader::Binding(std::string("frustumGridBuffer"), LIGHT_CLUSTER_GRID_FRUSTUM_GRID_SLOT)); + slotBindings.insert(gpu::Shader::Binding(std::string("clusterGridBuffer"), LIGHT_CLUSTER_GRID_CLUSTER_GRID_SLOT)); + slotBindings.insert(gpu::Shader::Binding(std::string("clusterContentBuffer"), LIGHT_CLUSTER_GRID_CLUSTER_CONTENT_SLOT)); + gpu::Shader::makeProgram(*program, slotBindings); @@ -327,6 +358,8 @@ const gpu::PipelinePointer DebugLightClusters::getDrawClusterFromDepthPipeline() gpu::Shader::BindingSet slotBindings; slotBindings.insert(gpu::Shader::Binding(std::string("frustumGridBuffer"), LIGHT_CLUSTER_GRID_FRUSTUM_GRID_SLOT)); + slotBindings.insert(gpu::Shader::Binding(std::string("clusterGridBuffer"), LIGHT_CLUSTER_GRID_CLUSTER_GRID_SLOT)); + slotBindings.insert(gpu::Shader::Binding(std::string("clusterContentBuffer"), LIGHT_CLUSTER_GRID_CLUSTER_CONTENT_SLOT)); slotBindings.insert(gpu::Shader::Binding(std::string("linearZeyeMap"), DEFERRED_BUFFER_LINEAR_DEPTH_UNIT)); slotBindings.insert(gpu::Shader::Binding(std::string("cameraCorrectionBuffer"), CAMERA_CORRECTION_BUFFER_SLOT)); slotBindings.insert(gpu::Shader::Binding(std::string("deferredFrameTransformBuffer"), DEFERRED_FRAME_TRANSFORM_BUFFER_SLOT)); @@ -401,6 +434,9 @@ void DebugLightClusters::run(const render::SceneContextPointer& sceneContext, co batch.setModelTransform(Transform()); batch.setUniformBuffer(LIGHT_CLUSTER_GRID_FRUSTUM_GRID_SLOT, lightClusters->_frustumGridBuffer); + batch.setUniformBuffer(LIGHT_CLUSTER_GRID_CLUSTER_GRID_SLOT, lightClusters->_clusterGridBuffer); + batch.setUniformBuffer(LIGHT_CLUSTER_GRID_CLUSTER_CONTENT_SLOT, lightClusters->_clusterContentBuffer); + if (doDrawClusterFromDepth) { @@ -422,8 +458,6 @@ void DebugLightClusters::run(const render::SceneContextPointer& sceneContext, co if (doDrawContent) { // bind the one gpu::Pipeline we need batch.setPipeline(getDrawClusterContentPipeline()); - batch.setUniformBuffer(LIGHT_CLUSTER_GRID_CLUSTER_GRID_SLOT, lightClusters->_clusterGridBuffer); - batch.setUniformBuffer(LIGHT_CLUSTER_GRID_CLUSTER_CONTENT_SLOT, lightClusters->_clusterContentBuffer); auto dims = lightClusters->_frustumGridBuffer->dims; glm::ivec3 summedDims(dims.x*dims.y * dims.z, dims.x*dims.y, dims.x); diff --git a/libraries/render-utils/src/LightClusters.h b/libraries/render-utils/src/LightClusters.h index 9930eda731..bef28a498a 100644 --- a/libraries/render-utils/src/LightClusters.h +++ b/libraries/render-utils/src/LightClusters.h @@ -24,7 +24,7 @@ public: float rangeFar { 100.0f }; float frustumFar { 10000.0f }; - glm::ivec3 dims { 8, 8, 8 }; + glm::ivec3 dims { 8, 8, 12 }; float spare; glm::mat4 eyeToGridProj; @@ -97,12 +97,21 @@ class LightClusteringPassConfig : public render::Job::Config { Q_OBJECT Q_PROPERTY(float rangeNear MEMBER rangeNear NOTIFY dirty) Q_PROPERTY(float rangeFar MEMBER rangeFar NOTIFY dirty) + + Q_PROPERTY(int dimX MEMBER dimX NOTIFY dirty) + Q_PROPERTY(int dimY MEMBER dimY NOTIFY dirty) + Q_PROPERTY(int dimZ MEMBER dimZ NOTIFY dirty) Q_PROPERTY(bool freeze MEMBER freeze NOTIFY dirty) public: LightClusteringPassConfig() : render::Job::Config(true){} float rangeNear{ 1.0f }; float rangeFar{ 512.0f }; + + int dimX { 8 }; + int dimY { 8 }; + int dimZ { 12 }; + bool freeze{ false }; signals: @@ -143,12 +152,14 @@ class DebugLightClustersConfig : public render::Job::Config { Q_OBJECT Q_PROPERTY(bool doDrawGrid MEMBER doDrawGrid NOTIFY dirty) Q_PROPERTY(bool doDrawClusterFromDepth MEMBER doDrawClusterFromDepth NOTIFY dirty) + Q_PROPERTY(bool doDrawContent MEMBER doDrawContent NOTIFY dirty) public: DebugLightClustersConfig() : render::Job::Config(true){} bool doDrawGrid{ false }; - bool doDrawClusterFromDepth{ false }; + bool doDrawClusterFromDepth { false }; + bool doDrawContent { false }; signals: void dirty(); @@ -179,9 +190,9 @@ protected: const gpu::PipelinePointer getDrawClusterGridPipeline(); const gpu::PipelinePointer getDrawClusterFromDepthPipeline(); const gpu::PipelinePointer getDrawClusterContentPipeline(); - bool doDrawGrid{ false }; + bool doDrawGrid { false }; bool doDrawClusterFromDepth { false }; - bool doDrawContent { true }; + bool doDrawContent { false }; }; #endif diff --git a/libraries/render-utils/src/lightClusters_drawClusterContent.slv b/libraries/render-utils/src/lightClusters_drawClusterContent.slv index a971bb5d2c..f976c7e245 100644 --- a/libraries/render-utils/src/lightClusters_drawClusterContent.slv +++ b/libraries/render-utils/src/lightClusters_drawClusterContent.slv @@ -53,22 +53,16 @@ void main(void) { ); vec4 pos = UNIT_BOX[UNIT_BOX_LINE_INDICES[gl_VertexID]]; - int clusterDesc = _clusterGridTable[gl_InstanceID]; - int numLights = 0xFFFF & (clusterDesc >> 16); - - if (numLights <= 0) { - return; - } - ivec3 dims = frustumGrid.dims.xyz; + - ivec3 summedDims = ivec3(dims.x * dims.y, dims.x, 1); + ivec2 cluster = clusterGrid_getCluster(gl_InstanceID); + int numLights = cluster.x; + float numLightsScale = clamp(numLights * 0.1, 0.01, 1.0); - int layer = gl_InstanceID / summedDims.x; - int offsetInLayer = gl_InstanceID % summedDims.x; - ivec3 clusterPos = ivec3(offsetInLayer % summedDims.y, offsetInLayer / summedDims.y, layer); + ivec3 clusterPos = clusterGrid_indexToCluster(gl_InstanceID); - - vec3 eyePos = frustumGrid_clusterPosToEye(clusterPos, vec3(0.05) + 0.9 * pos.xyz); + float boxScale = 0.99; + vec3 eyePos = frustumGrid_clusterPosToEye(clusterPos, vec3((1.0 - boxScale) * 0.5 + (1.0 - numLightsScale) * boxScale * 0.5) + numLightsScale * boxScale * pos.xyz); vec4 worldPos = frustumGrid_eyeToWorld(vec4(eyePos.xyz, 1.0)); diff --git a/libraries/render-utils/src/lightClusters_drawClusterFromDepth.slf b/libraries/render-utils/src/lightClusters_drawClusterFromDepth.slf index cd4f7fee63..bf98595399 100644 --- a/libraries/render-utils/src/lightClusters_drawClusterFromDepth.slf +++ b/libraries/render-utils/src/lightClusters_drawClusterFromDepth.slf @@ -36,6 +36,12 @@ void main(void) { vec4 clusterEyePos = frustumGrid_worldToEye(fragWorldPos); ivec3 clusterPos = frustumGrid_eyeToClusterPos(clusterEyePos.xyz); + + ivec2 cluster = clusterGrid_getCluster(clusterGrid_clusterToIndex(clusterPos)); + int numLights = cluster.x; + float numLightsScale = clamp(numLights * 0.1, 0.01, 1.0); + + ivec3 dims = frustumGrid.dims.xyz; dims.z +=1; ivec3 summedDims = ivec3(dims.x * dims.y, dims.x, 1); @@ -59,9 +65,9 @@ void main(void) { if (relClusterId < 0.0) { _fragColor = vec4(0.0); } else if (relClusterId >= 1.0) { - _fragColor = vec4(vec3(1.0), 0.5); + _fragColor = vec4(vec3(1.0), 0.2); } else { - _fragColor = vec4(colorWheel(fract(relClusterId)), 0.9); + _fragColor = vec4(colorWheel(fract(relClusterId)), 0.05 + 0.95 * numLightsScale); } } diff --git a/libraries/render-utils/src/local_lights_shading.slf b/libraries/render-utils/src/local_lights_shading.slf index b002382c91..4a27a258fb 100644 --- a/libraries/render-utils/src/local_lights_shading.slf +++ b/libraries/render-utils/src/local_lights_shading.slf @@ -25,11 +25,15 @@ uniform lightIndexBuffer { }; <@include LightingModel.slh@> + <@include LightPoint.slh@> <$declareLightingPoint(supportScattering)$> <@include LightSpot.slh@> <$declareLightingSpot(supportScattering)$> +<@include LightClusterGrid.slh@> + + in vec2 _texCoord0; out vec4 _fragColor; @@ -47,24 +51,54 @@ void main(void) { frag.position = fragPosition; + + // Frag pos in world + mat4 invViewMat = getViewInverse(); + vec4 fragPos = invViewMat * fragPosition; + + // From frag world pos find the cluster + vec4 clusterEyePos = frustumGrid_worldToEye(fragPos); + ivec3 clusterPos = frustumGrid_eyeToClusterPos(clusterEyePos.xyz); + + + ivec2 cluster = clusterGrid_getCluster(clusterGrid_clusterToIndex(clusterPos)); + int numLights = cluster.x; + if (numLights <= 0) { + discard; + } + + ivec3 dims = frustumGrid.dims.xyz; + if (clusterPos.x < 0 || clusterPos.x >= dims.x) { + discard; + } + + if (clusterPos.y < 0 || clusterPos.y >= dims.y) { + discard; + } + if (clusterPos.z < 0 || clusterPos.z > dims.z) { + discard; + } + + int lightClusterOffset = cluster.y; + + + vec4 midNormalCurvature; vec4 lowNormalCurvature; if (frag.mode == FRAG_MODE_SCATTERING) { unpackMidLowNormalCurvature(texCoord, midNormalCurvature, lowNormalCurvature); } - // Frag pos in world - mat4 invViewMat = getViewInverse(); - vec4 fragPos = invViewMat * fragPosition; // Frag to eye vec vec4 fragEyeVector = invViewMat * vec4(-frag.position.xyz, 0.0); vec3 fragEyeDir = normalize(fragEyeVector.xyz); - int numLights = lightIndex[0]; + // int numLights = lightIndex[0]; for (int i = 0; i < numLights; i++) { // Need the light now - Light light = getLight(lightIndex[i + 1]); + int theLightIndex = _clusterGridContent[lightClusterOffset + i]; + Light light = getLight(theLightIndex); bool isSpot = light_isSpot(light); // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space vec4 fragLightVecLen2; @@ -98,5 +132,7 @@ void main(void) { _fragColor.rgb += diffuse; _fragColor.rgb += specular; } + + // _fragColor.rgb += vec3(0.05, 0.0, 0.0); } diff --git a/scripts/developer/utilities/render/lightClustering.qml b/scripts/developer/utilities/render/lightClustering.qml index 9adb137b0f..622d858c62 100644 --- a/scripts/developer/utilities/render/lightClustering.qml +++ b/scripts/developer/utilities/render/lightClustering.qml @@ -34,7 +34,30 @@ Column { max: 500.0 min: 100.0 } - + ConfigSlider { + label: qsTr("Grid X") + integral: true + config: Render.getConfig("LightClustering") + property: "dimX" + max: 16 + min: 1 + } + ConfigSlider { + label: qsTr("Grid Y") + integral: true + config: Render.getConfig("LightClustering") + property: "dimY" + max: 16 + min: 1 + } + ConfigSlider { + label: qsTr("Grid Z") + integral: true + config: Render.getConfig("LightClustering") + property: "dimZ" + max: 15 + min: 1 + } CheckBox { text: "Freeze" checked: Render.getConfig("LightClustering")["freeze"] @@ -50,6 +73,11 @@ Column { checked: Render.getConfig("DebugLightClusters")["doDrawClusterFromDepth"] onCheckedChanged: { Render.getConfig("DebugLightClusters")["doDrawClusterFromDepth"] = checked } } + CheckBox { + text: "Draw Content" + checked: Render.getConfig("DebugLightClusters")["doDrawContent"] + onCheckedChanged: { Render.getConfig("DebugLightClusters")["doDrawContent"] = checked } + } } } } From fea5f8b03bd745b29868a952a1a5ff83b8abb626 Mon Sep 17 00:00:00 2001 From: samcake Date: Tue, 13 Sep 2016 16:03:57 -0700 Subject: [PATCH 31/75] best state for now --- libraries/render-utils/src/LightClusters.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/render-utils/src/LightClusters.cpp b/libraries/render-utils/src/LightClusters.cpp index a2feb2e471..fabfffd439 100644 --- a/libraries/render-utils/src/LightClusters.cpp +++ b/libraries/render-utils/src/LightClusters.cpp @@ -108,7 +108,7 @@ void LightClusters::updateClusters() { std::vector< std::vector< uint32_t > > clusterGrid(_numClusters); _clusterGrid.resize(_numClusters, EMPTY_CLUSTER); - uint32_t maxNumIndices = _clusterContent.size(); + uint32_t maxNumIndices = (uint32_t) _clusterContent.size(); _clusterContent.resize(maxNumIndices, INVALID_LIGHT); auto theFrustumGrid(_frustumGridBuffer.get()); From 124060d31af42bd87c8b909526a94cf544aa2363 Mon Sep 17 00:00:00 2001 From: samcake Date: Tue, 13 Sep 2016 17:44:19 -0700 Subject: [PATCH 32/75] Cleaning up a bit --- .../render-utils/src/LightClusterGrid.slh | 2 +- libraries/render-utils/src/LightClusters.cpp | 55 ++++++--- libraries/render-utils/src/LightClusters.h | 9 +- .../src/lightClusters_drawClusterContent.slv | 5 +- .../lightClusters_drawClusterFromDepth.slf | 2 +- .../utilities/render/lightClustering.js | 4 +- .../utilities/render/lightClustering.qml | 109 +++++++++++------- 7 files changed, 118 insertions(+), 68 deletions(-) diff --git a/libraries/render-utils/src/LightClusterGrid.slh b/libraries/render-utils/src/LightClusterGrid.slh index c70d0d2c6b..af046ce11d 100644 --- a/libraries/render-utils/src/LightClusterGrid.slh +++ b/libraries/render-utils/src/LightClusterGrid.slh @@ -52,7 +52,7 @@ uniform clusterGridBuffer { }; uniform clusterContentBuffer { - int _clusterGridContent[10000]; + int _clusterGridContent[16384]; }; int clusterGrid_clusterToIndex(ivec3 pos) { diff --git a/libraries/render-utils/src/LightClusters.cpp b/libraries/render-utils/src/LightClusters.cpp index fabfffd439..4de51af6da 100644 --- a/libraries/render-utils/src/LightClusters.cpp +++ b/libraries/render-utils/src/LightClusters.cpp @@ -42,22 +42,43 @@ enum LightClusterGridShader_BufferSlot { #include "DeferredLightingEffect.h" +const glm::uvec4 LightClusters::MAX_GRID_DIMENSIONS { 16, 16, 15, 16384 }; + + LightClusters::LightClusters() : _lightIndicesBuffer(std::make_shared()), _clusterGridBuffer(std::make_shared(), gpu::Element::INDEX_INT32), _clusterContentBuffer(std::make_shared(), gpu::Element::INDEX_INT32) { - setDimensions(_frustumGridBuffer->dims, 10000); + setDimensions(_frustumGridBuffer->dims, MAX_GRID_DIMENSIONS.w); } void LightClusters::setDimensions(glm::uvec3 gridDims, uint32_t listBudget) { - _frustumGridBuffer.edit().dims = gridDims; + ivec3 configDimensions; + configDimensions.x = std::min(MAX_GRID_DIMENSIONS.x, gridDims.x); + configDimensions.y = std::min(MAX_GRID_DIMENSIONS.y, gridDims.y); + configDimensions.z = std::min(MAX_GRID_DIMENSIONS.z, gridDims.z); - _numClusters = _frustumGridBuffer.edit().frustumGrid_numClusters(); + auto configListBudget = std::min(MAX_GRID_DIMENSIONS.w, listBudget); - _clusterGridBuffer._size = _clusterGridBuffer._buffer->resize(_numClusters * sizeof(uint32_t)); - _clusterContentBuffer._size = _clusterContentBuffer._buffer->resize(listBudget * sizeof(uint32_t)); - _clusterGrid.resize(_numClusters, EMPTY_CLUSTER); - _clusterContent.resize(listBudget, INVALID_LIGHT); + auto& dims = _frustumGridBuffer->dims; + if ((dims.x != configDimensions.x) || (dims.y != configDimensions.y) || (dims.z != configDimensions.z)) { + _frustumGridBuffer.edit().dims = configDimensions; + } + + auto numClusters = _frustumGridBuffer.edit().frustumGrid_numClusters(); + if (numClusters != _numClusters) { + _numClusters = numClusters; + _clusterGrid.clear(); + _clusterGrid.resize(_numClusters, EMPTY_CLUSTER); + _clusterGridBuffer._size = _clusterGridBuffer._buffer->resize(_numClusters * sizeof(uint32_t)); + } + + + if (configListBudget != _clusterContentBuffer.getNumElements()) { + _clusterContent.clear(); + _clusterContent.resize(configListBudget, INVALID_LIGHT); + _clusterContentBuffer._size = _clusterContentBuffer._buffer->resize(configListBudget * sizeof(LightID)); + } } @@ -105,7 +126,7 @@ void LightClusters::updateLightFrame(const LightStage::Frame& lightFrame, bool p void LightClusters::updateClusters() { // Clean up last info - std::vector< std::vector< uint32_t > > clusterGrid(_numClusters); + std::vector< std::vector< LightID > > clusterGrid(_numClusters); _clusterGrid.resize(_numClusters, EMPTY_CLUSTER); uint32_t maxNumIndices = (uint32_t) _clusterContent.size(); @@ -228,6 +249,10 @@ void LightClusters::updateClusters() { } } } + + if (numClusterTouched >= maxNumIndices) { + break; + } } // Lights have been gathered now reexpress in terms of 2 sequential buffers @@ -241,7 +266,7 @@ void LightClusters::updateClusters() { _clusterGrid[i] = (uint32_t)((numLights << 16) | offset); if (numLights) { - memcpy(_clusterContent.data() + indexOffset, cluster.data(), numLights * sizeof(uint32_t)); + memcpy(_clusterContent.data() + indexOffset, cluster.data(), numLights * sizeof(LightID)); } indexOffset += numLights; @@ -249,7 +274,7 @@ void LightClusters::updateClusters() { // update the buffers _clusterGridBuffer._buffer->setData(_clusterGridBuffer._size, (gpu::Byte*) _clusterGrid.data()); - _clusterContentBuffer._buffer->setSubData(0, indexOffset * sizeof(uint32_t), (gpu::Byte*) _clusterContent.data()); + _clusterContentBuffer._buffer->setSubData(0, indexOffset * sizeof(LightID), (gpu::Byte*) _clusterContent.data()); } @@ -267,15 +292,7 @@ void LightClusteringPass::configure(const Config& config) { _lightClusters->_frustumGridBuffer.edit().rangeFar = config.rangeFar; } - ivec3 configDimensions; - configDimensions.x = std::max(0, std::min(16, config.dimX)); - configDimensions.y = std::max(0, std::min(16, config.dimY)); - configDimensions.z = std::max(0, std::min(15, config.dimZ)); - - auto& dims = _lightClusters->_frustumGridBuffer->dims; - if ((dims.x != configDimensions.x) || (dims.y != configDimensions.y) || (dims.z != configDimensions.z)) { - _lightClusters->setDimensions(configDimensions, 10000); - } + _lightClusters->setDimensions(glm::uvec3(config.dimX, config.dimY, config.dimZ), 10000); } _freeze = config.freeze; diff --git a/libraries/render-utils/src/LightClusters.h b/libraries/render-utils/src/LightClusters.h index bef28a498a..5d64b17ca1 100644 --- a/libraries/render-utils/src/LightClusters.h +++ b/libraries/render-utils/src/LightClusters.h @@ -54,7 +54,10 @@ public: class LightClusters { public: - + using LightID = LightStage::Index; + + static const glm::uvec4 MAX_GRID_DIMENSIONS; + LightClusters(); void setDimensions(glm::uvec3 gridDims, uint32_t listBudget); @@ -81,10 +84,10 @@ public: uint32_t _numClusters { 0 }; const uint32_t EMPTY_CLUSTER { 0x0000FFFF }; - const uint32_t INVALID_LIGHT { 0xFFFFFFFF }; + const LightID INVALID_LIGHT { LightStage::INVALID_INDEX }; std::vector _clusterGrid; - std::vector _clusterContent; + std::vector _clusterContent; gpu::BufferView _clusterGridBuffer; gpu::BufferView _clusterContentBuffer; }; diff --git a/libraries/render-utils/src/lightClusters_drawClusterContent.slv b/libraries/render-utils/src/lightClusters_drawClusterContent.slv index f976c7e245..af3cf3e3ac 100644 --- a/libraries/render-utils/src/lightClusters_drawClusterContent.slv +++ b/libraries/render-utils/src/lightClusters_drawClusterContent.slv @@ -57,7 +57,8 @@ void main(void) { ivec2 cluster = clusterGrid_getCluster(gl_InstanceID); int numLights = cluster.x; - float numLightsScale = clamp(numLights * 0.1, 0.01, 1.0); + + float numLightsScale = clamp(numLights * 0.1, 0.0, 1.0); ivec3 clusterPos = clusterGrid_indexToCluster(gl_InstanceID); @@ -70,5 +71,5 @@ void main(void) { TransformCamera cam = getTransformCamera(); <$transformWorldToClipPos(cam, worldPos, gl_Position)$> - varColor = vec4(colorWheel(fract(float(gl_InstanceID) / float(frustumGrid_numClusters()))), 0.9); + varColor = vec4(colorWheel(fract(float(gl_InstanceID) / float(frustumGrid_numClusters()))), (numLights >0 ? 0.9 : 0.1)); } \ No newline at end of file diff --git a/libraries/render-utils/src/lightClusters_drawClusterFromDepth.slf b/libraries/render-utils/src/lightClusters_drawClusterFromDepth.slf index bf98595399..e711c6fc64 100644 --- a/libraries/render-utils/src/lightClusters_drawClusterFromDepth.slf +++ b/libraries/render-utils/src/lightClusters_drawClusterFromDepth.slf @@ -67,7 +67,7 @@ void main(void) { } else if (relClusterId >= 1.0) { _fragColor = vec4(vec3(1.0), 0.2); } else { - _fragColor = vec4(colorWheel(fract(relClusterId)), 0.05 + 0.95 * numLightsScale); + _fragColor = vec4(colorWheel(fract(relClusterId)), (numLights > 0 ? 0.05 + 0.95 * numLightsScale : 0.0)); } } diff --git a/scripts/developer/utilities/render/lightClustering.js b/scripts/developer/utilities/render/lightClustering.js index bad023a64f..7fb9416d40 100644 --- a/scripts/developer/utilities/render/lightClustering.js +++ b/scripts/developer/utilities/render/lightClustering.js @@ -15,7 +15,7 @@ var window = new OverlayWindow({ title: 'Light Clustering', source: qml, width: 400, - height: 200 + height: 300 }); -window.setPosition(Window.innerWidth - 420, 50 + 250 + 50); +window.setPosition(Window.innerWidth - 420, 50 + 250 + 50 + 250 + 50 ); window.closed.connect(function() { Script.stop(); }); \ No newline at end of file diff --git a/scripts/developer/utilities/render/lightClustering.qml b/scripts/developer/utilities/render/lightClustering.qml index 622d858c62..562e7c5556 100644 --- a/scripts/developer/utilities/render/lightClustering.qml +++ b/scripts/developer/utilities/render/lightClustering.qml @@ -10,6 +10,7 @@ import QtQuick 2.5 import QtQuick.Controls 1.4 import "configSlider" +import "../lib/plotperf" Column { spacing: 8 @@ -18,46 +19,73 @@ Column { spacing: 10 Column{ - ConfigSlider { - label: qsTr("Range Near [m]") - integral: false - config: Render.getConfig("LightClustering") - property: "rangeNear" - max: 20.0 - min: 0.1 - } - ConfigSlider { - label: qsTr("Range Far [m]") - integral: false - config: Render.getConfig("LightClustering") - property: "rangeFar" - max: 500.0 - min: 100.0 - } - ConfigSlider { - label: qsTr("Grid X") - integral: true - config: Render.getConfig("LightClustering") - property: "dimX" - max: 16 - min: 1 - } - ConfigSlider { - label: qsTr("Grid Y") - integral: true - config: Render.getConfig("LightClustering") - property: "dimY" - max: 16 - min: 1 - } - ConfigSlider { - label: qsTr("Grid Z") - integral: true - config: Render.getConfig("LightClustering") - property: "dimZ" - max: 15 - min: 1 - } + PlotPerf { + title: "Light CLustering Timing" + height: 50 + object: Render.getConfig("LightClustering") + valueUnit: "ms" + valueScale: 1 + valueNumDigits: "4" + plots: [ + { + object: Render.getConfig("LightClustering"), + prop: "cpuRunTime", + label: "time", + scale: 1, + color: "#FFFFFF" + }, + { + object: Render.getConfig("DrawLight"), + prop: "numDrawn", + unit: "", + scale: 0.01, + numDigits: 0, + label: "Lights", + color: "#FED959" + } + ] + } + + ConfigSlider { + label: qsTr("Range Near [m]") + integral: false + config: Render.getConfig("LightClustering") + property: "rangeNear" + max: 20.0 + min: 0.1 + } + ConfigSlider { + label: qsTr("Range Far [m]") + integral: false + config: Render.getConfig("LightClustering") + property: "rangeFar" + max: 500.0 + min: 100.0 + } + ConfigSlider { + label: qsTr("Grid X") + integral: true + config: Render.getConfig("LightClustering") + property: "dimX" + max: 16 + min: 1 + } + ConfigSlider { + label: qsTr("Grid Y") + integral: true + config: Render.getConfig("LightClustering") + property: "dimY" + max: 16 + min: 1 + } + ConfigSlider { + label: qsTr("Grid Z") + integral: true + config: Render.getConfig("LightClustering") + property: "dimZ" + max: 15 + min: 1 + } CheckBox { text: "Freeze" checked: Render.getConfig("LightClustering")["freeze"] @@ -78,6 +106,7 @@ Column { checked: Render.getConfig("DebugLightClusters")["doDrawContent"] onCheckedChanged: { Render.getConfig("DebugLightClusters")["doDrawContent"] = checked } } + } } } From c622849481525e1c578d59dcc43c88f1c963066a Mon Sep 17 00:00:00 2001 From: samcake Date: Tue, 13 Sep 2016 17:59:06 -0700 Subject: [PATCH 33/75] Splitting the frustum culling test horizontal and vertical --- libraries/render-utils/src/LightClusters.cpp | 47 +++++++++++++------- 1 file changed, 30 insertions(+), 17 deletions(-) diff --git a/libraries/render-utils/src/LightClusters.cpp b/libraries/render-utils/src/LightClusters.cpp index 4de51af6da..ef584ae104 100644 --- a/libraries/render-utils/src/LightClusters.cpp +++ b/libraries/render-utils/src/LightClusters.cpp @@ -192,51 +192,64 @@ void LightClusters::updateClusters() { float eyeOriLen2H = glm::length2(eyeOriH); float eyeOriLen2V = glm::length2(eyeOriV); - if ((eyeOriLen2H > radius2) && (eyeOriLen2V > radius2)) { + if ((eyeOriLen2H > radius2)) { float eyeOriLenH = sqrt(eyeOriLen2H); - float eyeOriLenV = sqrt(eyeOriLen2V); auto eyeOriDirH = glm::vec3(eyeOriH) / eyeOriLenH; - auto eyeOriDirV = glm::vec3(eyeOriV) / eyeOriLenV; - - float eyeToTangentCircleLenH = sqrt(eyeOriLen2H - radius2); - float eyeToTangentCircleLenV = sqrt(eyeOriLen2V - radius2); float eyeToTangentCircleTanH = radius / eyeToTangentCircleLenH; - float eyeToTangentCircleTanV = radius / eyeToTangentCircleLenV; float eyeToTangentCircleCosH = eyeToTangentCircleLenH / eyeOriLenH; - float eyeToTangentCircleCosV = eyeToTangentCircleLenV / eyeOriLenV; float eyeToTangentCircleSinH = radius / eyeOriLenH; - float eyeToTangentCircleSinV = radius / eyeOriLenV; // rotate the eyeToOriDir (H & V) in both directions glm::vec3 leftDir(eyeOriDirH.x * eyeToTangentCircleCosH + eyeOriDirH.z * eyeToTangentCircleSinH, 0.0f, eyeOriDirH.x * -eyeToTangentCircleSinH + eyeOriDirH.z * eyeToTangentCircleCosH); glm::vec3 rightDir(eyeOriDirH.x * eyeToTangentCircleCosH - eyeOriDirH.z * eyeToTangentCircleSinH, 0.0f, eyeOriDirH.x * eyeToTangentCircleSinH + eyeOriDirH.z * eyeToTangentCircleCosH); - glm::vec3 bottomDir(0.0f, eyeOriDirV.y * eyeToTangentCircleCosV + eyeOriDirV.z * eyeToTangentCircleSinV, eyeOriDirV.y * -eyeToTangentCircleSinV + eyeOriDirV.z * eyeToTangentCircleCosV); - glm::vec3 topDir(0.0f, eyeOriDirV.y * eyeToTangentCircleCosV - eyeOriDirV.z * eyeToTangentCircleSinV, eyeOriDirV.y * eyeToTangentCircleSinV + eyeOriDirV.z * eyeToTangentCircleCosV); glm::vec3 leftPosAtNear = leftDir * theFrustumGrid.rangeNear * 2.0f; glm::vec3 rightPosAtNear = rightDir * theFrustumGrid.rangeNear * 2.0f; - glm::vec3 bottomPosAtNear = bottomDir * theFrustumGrid.rangeNear * 2.0f; - glm::vec3 topPosAtNear = topDir * theFrustumGrid.rangeNear * 2.0f; auto lc = theFrustumGrid.frustumGrid_eyeToClusterPos(leftPosAtNear); auto rc = theFrustumGrid.frustumGrid_eyeToClusterPos(rightPosAtNear); - auto bc = theFrustumGrid.frustumGrid_eyeToClusterPos(bottomPosAtNear); - auto tc = theFrustumGrid.frustumGrid_eyeToClusterPos(topPosAtNear); xMin = std::max(0, lc.x); xMax = std::max(0, std::min(rc.x, xMax)); + } + + if ((eyeOriLen2V > radius2)) { + float eyeOriLenV = sqrt(eyeOriLen2V); + + auto eyeOriDirV = glm::vec3(eyeOriV) / eyeOriLenV; + + + + float eyeToTangentCircleLenV = sqrt(eyeOriLen2V - radius2); + + float eyeToTangentCircleTanV = radius / eyeToTangentCircleLenV; + + float eyeToTangentCircleCosV = eyeToTangentCircleLenV / eyeOriLenV; + + float eyeToTangentCircleSinV = radius / eyeOriLenV; + + + // rotate the eyeToOriDir (H & V) in both directions + glm::vec3 bottomDir(0.0f, eyeOriDirV.y * eyeToTangentCircleCosV + eyeOriDirV.z * eyeToTangentCircleSinV, eyeOriDirV.y * -eyeToTangentCircleSinV + eyeOriDirV.z * eyeToTangentCircleCosV); + glm::vec3 topDir(0.0f, eyeOriDirV.y * eyeToTangentCircleCosV - eyeOriDirV.z * eyeToTangentCircleSinV, eyeOriDirV.y * eyeToTangentCircleSinV + eyeOriDirV.z * eyeToTangentCircleCosV); + + + glm::vec3 bottomPosAtNear = bottomDir * theFrustumGrid.rangeNear * 2.0f; + glm::vec3 topPosAtNear = topDir * theFrustumGrid.rangeNear * 2.0f; + + auto bc = theFrustumGrid.frustumGrid_eyeToClusterPos(bottomPosAtNear); + auto tc = theFrustumGrid.frustumGrid_eyeToClusterPos(topPosAtNear); + yMin = std::max(0, bc.y); yMax = std::max(0, std::min(tc.y, yMax)); - - } // now voxelize From af48d4f0bdf999a59d5109a7f5ff83f94c102a49 Mon Sep 17 00:00:00 2001 From: samcake Date: Wed, 14 Sep 2016 09:28:51 -0700 Subject: [PATCH 34/75] fetch the cluster content through a function to be able to change the implementation --- libraries/render-utils/src/LightClusterGrid.slh | 4 ++++ libraries/render-utils/src/local_lights_shading.slf | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/libraries/render-utils/src/LightClusterGrid.slh b/libraries/render-utils/src/LightClusterGrid.slh index af046ce11d..ceb3f79e89 100644 --- a/libraries/render-utils/src/LightClusterGrid.slh +++ b/libraries/render-utils/src/LightClusterGrid.slh @@ -73,4 +73,8 @@ ivec2 clusterGrid_getCluster(int index) { return ivec2(numLights, contentOffset); } +int clusterGrid_getClusterLightId(int index, ivec2 cluster) { + return _clusterGridContent[cluster.y + index]; +} + <@endif@> diff --git a/libraries/render-utils/src/local_lights_shading.slf b/libraries/render-utils/src/local_lights_shading.slf index 4a27a258fb..2b8beb67c3 100644 --- a/libraries/render-utils/src/local_lights_shading.slf +++ b/libraries/render-utils/src/local_lights_shading.slf @@ -97,7 +97,7 @@ void main(void) { // int numLights = lightIndex[0]; for (int i = 0; i < numLights; i++) { // Need the light now - int theLightIndex = _clusterGridContent[lightClusterOffset + i]; + int theLightIndex = clusterGrid_getClusterLightId(i, cluster); Light light = getLight(theLightIndex); bool isSpot = light_isSpot(light); // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space From fdba78db6f3badc8789c8c910420ec53e8db1625 Mon Sep 17 00:00:00 2001 From: samcake Date: Wed, 14 Sep 2016 16:36:01 -0700 Subject: [PATCH 35/75] Better vizualization, first set of culling improvment --- .../src/LightClusterGrid_shared.slh | 32 +++++++++ libraries/render-utils/src/LightClusters.cpp | 67 ++++++++++--------- libraries/render-utils/src/LightClusters.h | 2 +- .../src/lightClusters_drawClusterContent.slv | 8 +-- .../src/lightClusters_drawGrid.slv | 13 ++-- 5 files changed, 76 insertions(+), 46 deletions(-) diff --git a/libraries/render-utils/src/LightClusterGrid_shared.slh b/libraries/render-utils/src/LightClusterGrid_shared.slh index 4ce469deba..da4931a91e 100644 --- a/libraries/render-utils/src/LightClusterGrid_shared.slh +++ b/libraries/render-utils/src/LightClusterGrid_shared.slh @@ -123,6 +123,38 @@ ivec3 frustumGrid_eyeToClusterPos(vec3 eyePos) { return ivec3(gridPos); } +int frustumGrid_eyeToClusterDirH(vec3 eyeDir) { + if (eyeDir.z >= 0.0) { + return (eyeDir.x > 0 ? frustumGrid.dims.x : -1); + } + + float eyeDepth = -eyeDir.z; + float nclipDir = eyeDir.x / eyeDepth; + float ndcDir = nclipDir * frustumGrid.eyeToGridProj[0][0] - frustumGrid.eyeToGridProj[2][0]; + float volumeDir = 0.5 * (ndcDir + 1.0); + float gridPos = volumeDir * float(frustumGrid.dims.x); + + return int(gridPos); +} + +int frustumGrid_eyeToClusterDirV(vec3 eyeDir) { + if (eyeDir.z >= 0.0) { + return (eyeDir.y > 0 ? frustumGrid.dims.y : -1); + } + + float eyeDepth = -eyeDir.z; + float nclipDir = eyeDir.y / eyeDepth; + float ndcDir = nclipDir * frustumGrid.eyeToGridProj[1][1] - frustumGrid.eyeToGridProj[2][1]; + float volumeDir = 0.5 * (ndcDir + 1.0); + float gridPos = volumeDir * float(frustumGrid.dims.y); + + return int(gridPos); +} + +ivec2 frustumGrid_eyeToClusterDir(vec3 eyeDir) { + return ivec2(frustumGrid_eyeToClusterDirH(eyeDir), frustumGrid_eyeToClusterDirV(eyeDir)); +} + vec4 frustumGrid_eyeToWorld(vec4 eyePos) { return frustumGrid.eyeToWorldMat * eyePos; } diff --git a/libraries/render-utils/src/LightClusters.cpp b/libraries/render-utils/src/LightClusters.cpp index ef584ae104..707e82ae2f 100644 --- a/libraries/render-utils/src/LightClusters.cpp +++ b/libraries/render-utils/src/LightClusters.cpp @@ -124,6 +124,27 @@ void LightClusters::updateLightFrame(const LightStage::Frame& lightFrame, bool p _lightIndicesBuffer._size = _visibleLightIndices.size() * sizeof(int); } +bool scanLightVolume(FrustumGrid& grid, int zMin, int zMax, int yMin, int yMax, int xMin, int xMax, LightClusters::LightID lightId, const glm::vec4& eyePosRadius, + uint32_t& numClustersTouched, int maxNumIndices, std::vector< std::vector>& clusterGrid) { + glm::ivec3 gridPosToOffset(1, grid.dims.x, grid.dims.x * grid.dims.y); + + bool hasBudget = true; + for (auto z = zMin; (z <= zMax) && hasBudget; z++) { + for (auto y = yMin; (y <= yMax) && hasBudget; y++) { + for (auto x = xMin; (x <= xMax) && hasBudget; x++) { + auto index = x + gridPosToOffset.y * y + gridPosToOffset.z * z; + clusterGrid[index].emplace_back(lightId); + numClustersTouched++; + if (numClustersTouched >= maxNumIndices) { + hasBudget = false; + } + } + } + } + + return hasBudget; +} + void LightClusters::updateClusters() { // Clean up last info std::vector< std::vector< LightID > > clusterGrid(_numClusters); @@ -167,7 +188,8 @@ void LightClusters::updateClusters() { continue; } - + // is it a light whose origin is behind the near ? + bool behindLight = (eyeOri.z >= -theFrustumGrid.rangeNear); // float eyeOriLen2 = glm::length2(eyeOri); @@ -199,8 +221,6 @@ void LightClusters::updateClusters() { float eyeToTangentCircleLenH = sqrt(eyeOriLen2H - radius2); - float eyeToTangentCircleTanH = radius / eyeToTangentCircleLenH; - float eyeToTangentCircleCosH = eyeToTangentCircleLenH / eyeOriLenH; float eyeToTangentCircleSinH = radius / eyeOriLenH; @@ -210,15 +230,11 @@ void LightClusters::updateClusters() { glm::vec3 leftDir(eyeOriDirH.x * eyeToTangentCircleCosH + eyeOriDirH.z * eyeToTangentCircleSinH, 0.0f, eyeOriDirH.x * -eyeToTangentCircleSinH + eyeOriDirH.z * eyeToTangentCircleCosH); glm::vec3 rightDir(eyeOriDirH.x * eyeToTangentCircleCosH - eyeOriDirH.z * eyeToTangentCircleSinH, 0.0f, eyeOriDirH.x * eyeToTangentCircleSinH + eyeOriDirH.z * eyeToTangentCircleCosH); + auto lc = theFrustumGrid.frustumGrid_eyeToClusterDirH(leftDir); + auto rc = theFrustumGrid.frustumGrid_eyeToClusterDirH(rightDir); - glm::vec3 leftPosAtNear = leftDir * theFrustumGrid.rangeNear * 2.0f; - glm::vec3 rightPosAtNear = rightDir * theFrustumGrid.rangeNear * 2.0f; - - auto lc = theFrustumGrid.frustumGrid_eyeToClusterPos(leftPosAtNear); - auto rc = theFrustumGrid.frustumGrid_eyeToClusterPos(rightPosAtNear); - - xMin = std::max(0, lc.x); - xMax = std::max(0, std::min(rc.x, xMax)); + xMin = std::max(xMin, lc); + xMax = std::max(0, std::min(rc, xMax)); } if ((eyeOriLen2V > radius2)) { @@ -226,12 +242,8 @@ void LightClusters::updateClusters() { auto eyeOriDirV = glm::vec3(eyeOriV) / eyeOriLenV; - - float eyeToTangentCircleLenV = sqrt(eyeOriLen2V - radius2); - float eyeToTangentCircleTanV = radius / eyeToTangentCircleLenV; - float eyeToTangentCircleCosV = eyeToTangentCircleLenV / eyeOriLenV; float eyeToTangentCircleSinV = radius / eyeOriLenV; @@ -241,29 +253,17 @@ void LightClusters::updateClusters() { glm::vec3 bottomDir(0.0f, eyeOriDirV.y * eyeToTangentCircleCosV + eyeOriDirV.z * eyeToTangentCircleSinV, eyeOriDirV.y * -eyeToTangentCircleSinV + eyeOriDirV.z * eyeToTangentCircleCosV); glm::vec3 topDir(0.0f, eyeOriDirV.y * eyeToTangentCircleCosV - eyeOriDirV.z * eyeToTangentCircleSinV, eyeOriDirV.y * eyeToTangentCircleSinV + eyeOriDirV.z * eyeToTangentCircleCosV); + auto bc = theFrustumGrid.frustumGrid_eyeToClusterDirV(bottomDir); + auto tc = theFrustumGrid.frustumGrid_eyeToClusterDirV(topDir); - glm::vec3 bottomPosAtNear = bottomDir * theFrustumGrid.rangeNear * 2.0f; - glm::vec3 topPosAtNear = topDir * theFrustumGrid.rangeNear * 2.0f; - - auto bc = theFrustumGrid.frustumGrid_eyeToClusterPos(bottomPosAtNear); - auto tc = theFrustumGrid.frustumGrid_eyeToClusterPos(topPosAtNear); - - yMin = std::max(0, bc.y); - yMax = std::max(0, std::min(tc.y, yMax)); + yMin = std::max(yMin, bc); + yMax = std::max(yMin, std::min(tc, yMax)); } // now voxelize - for (auto z = zMin; z <= zMax; z++) { - for (auto y = yMin; y <= yMax; y++) { - for (auto x = xMin; x <= xMax; x++) { - auto index = x + gridPosToOffset.y * y + gridPosToOffset.z * z; - clusterGrid[index].emplace_back(lightId); - numClusterTouched++; - } - } - } + bool hasBudget = scanLightVolume(theFrustumGrid, zMin, zMax, yMin, yMax, xMin, xMax, lightId, glm::vec4(glm::vec3(eyeOri), radius), numClusterTouched, maxNumIndices, clusterGrid); - if (numClusterTouched >= maxNumIndices) { + if (!hasBudget) { break; } } @@ -486,6 +486,7 @@ void DebugLightClusters::run(const render::SceneContextPointer& sceneContext, co } if (doDrawContent) { + // bind the one gpu::Pipeline we need batch.setPipeline(getDrawClusterContentPipeline()); diff --git a/libraries/render-utils/src/LightClusters.h b/libraries/render-utils/src/LightClusters.h index 5d64b17ca1..e5d0275d85 100644 --- a/libraries/render-utils/src/LightClusters.h +++ b/libraries/render-utils/src/LightClusters.h @@ -74,7 +74,7 @@ public: LightStagePointer _lightStage; - + gpu::StructBuffer _frustumGridBuffer; diff --git a/libraries/render-utils/src/lightClusters_drawClusterContent.slv b/libraries/render-utils/src/lightClusters_drawClusterContent.slv index af3cf3e3ac..d146d8b691 100644 --- a/libraries/render-utils/src/lightClusters_drawClusterContent.slv +++ b/libraries/render-utils/src/lightClusters_drawClusterContent.slv @@ -1,4 +1,4 @@ -<@include gpu/Config.slh@> +<@include gpu / Config.slh@> <$VERSION_HEADER$> // Generated on <$_SCRIBE_DATE$> // @@ -12,17 +12,15 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -<@include gpu/Transform.slh@> +<@include gpu / Transform.slh@> <$declareStandardTransform()$> <@include LightClusterGrid.slh@> -<@include gpu/Color.slh@> +<@include gpu / Color.slh@> <$declareColorWheel()$> - - out vec4 varColor; diff --git a/libraries/render-utils/src/lightClusters_drawGrid.slv b/libraries/render-utils/src/lightClusters_drawGrid.slv index 9eb80cb28e..0eec0d04ee 100644 --- a/libraries/render-utils/src/lightClusters_drawGrid.slv +++ b/libraries/render-utils/src/lightClusters_drawGrid.slv @@ -53,16 +53,15 @@ void main(void) { ); vec4 pos = UNIT_BOX[UNIT_BOX_LINE_INDICES[gl_VertexID]]; - ivec3 dims = frustumGrid.dims.xyz; - ivec3 summedDims = ivec3(dims.x * dims.y, dims.x, 1); + ivec2 cluster = clusterGrid_getCluster(gl_InstanceID); + int numLights = cluster.x; - int layer = gl_InstanceID / summedDims.x; - int offsetInLayer = gl_InstanceID % summedDims.x; - ivec3 clusterPos = ivec3(offsetInLayer % summedDims.y, offsetInLayer / summedDims.y, layer); + ivec3 clusterPos = clusterGrid_indexToCluster(gl_InstanceID); - vec3 eyePos = frustumGrid_clusterPosToEye(clusterPos, vec3(0.05) + 0.9 * pos.xyz); + float boxScale = 1.0; + vec3 eyePos = frustumGrid_clusterPosToEye(clusterPos, vec3(1.0 - boxScale) * 0.5 + boxScale * pos.xyz); vec4 worldPos = frustumGrid_eyeToWorld(vec4(eyePos.xyz, 1.0)); @@ -70,5 +69,5 @@ void main(void) { TransformCamera cam = getTransformCamera(); <$transformWorldToClipPos(cam, worldPos, gl_Position)$> - varColor = vec4(colorWheel(fract(float(gl_InstanceID) / float(frustumGrid_numClusters()))), 0.9); + varColor = vec4(colorWheel(fract(float(gl_InstanceID) / float(frustumGrid_numClusters()))), (numLights > 0 ? 0.9 : 0.0)); } \ No newline at end of file From e0536a84e2485926c520eb394c6be6b3b9b1c5d7 Mon Sep 17 00:00:00 2001 From: samcake Date: Wed, 14 Sep 2016 17:18:39 -0700 Subject: [PATCH 36/75] Minor fix for compilation --- libraries/render-utils/src/LightClusters.cpp | 26 ++++++++++++++++--- libraries/render-utils/src/LightClusters.h | 10 +++++++ .../src/lightClusters_drawClusterContent.slv | 6 ++--- 3 files changed, 36 insertions(+), 6 deletions(-) diff --git a/libraries/render-utils/src/LightClusters.cpp b/libraries/render-utils/src/LightClusters.cpp index 707e82ae2f..cbea9a2a2a 100644 --- a/libraries/render-utils/src/LightClusters.cpp +++ b/libraries/render-utils/src/LightClusters.cpp @@ -40,6 +40,23 @@ enum LightClusterGridShader_BufferSlot { LIGHT_CLUSTER_GRID_CLUSTER_CONTENT_SLOT, }; + +void FrustumGrid::generateGridPlanes(Planes& xPlanes, Planes& yPlanes, Planes& zPlanes) { + xPlanes.resize(dims.x + 1); + yPlanes.resize(dims.y + 1); + zPlanes.resize(dims.z + 1); + + + for (int z = 0; z < xPlanes.size(); z++) { + ivec3 pos(0, 0, z); + zPlanes[z] = glm::vec4(0.0f, 0.0f, -1.0f, frustumGrid_clusterPosToEye(pos, vec3(0.0)).z); + } + + for (int x = 0; x < xPlanes.size(); x++) { + + } +} + #include "DeferredLightingEffect.h" const glm::uvec4 LightClusters::MAX_GRID_DIMENSIONS { 16, 16, 15, 16384 }; @@ -49,7 +66,9 @@ LightClusters::LightClusters() : _lightIndicesBuffer(std::make_shared()), _clusterGridBuffer(std::make_shared(), gpu::Element::INDEX_INT32), _clusterContentBuffer(std::make_shared(), gpu::Element::INDEX_INT32) { - setDimensions(_frustumGridBuffer->dims, MAX_GRID_DIMENSIONS.w); + auto dims = _frustumGridBuffer.edit().dims; + _frustumGridBuffer.edit().dims = ivec3(0); // make sure we go through the full reset of the dimensionts ion the setDImensions call + setDimensions(dims, MAX_GRID_DIMENSIONS.w); } void LightClusters::setDimensions(glm::uvec3 gridDims, uint32_t listBudget) { @@ -63,6 +82,7 @@ void LightClusters::setDimensions(glm::uvec3 gridDims, uint32_t listBudget) { auto& dims = _frustumGridBuffer->dims; if ((dims.x != configDimensions.x) || (dims.y != configDimensions.y) || (dims.z != configDimensions.z)) { _frustumGridBuffer.edit().dims = configDimensions; + _frustumGridBuffer.edit().generateGridPlanes(_gridPlanes[0], _gridPlanes[1], _gridPlanes[2]); } auto numClusters = _frustumGridBuffer.edit().frustumGrid_numClusters(); @@ -124,7 +144,7 @@ void LightClusters::updateLightFrame(const LightStage::Frame& lightFrame, bool p _lightIndicesBuffer._size = _visibleLightIndices.size() * sizeof(int); } -bool scanLightVolume(FrustumGrid& grid, int zMin, int zMax, int yMin, int yMax, int xMin, int xMax, LightClusters::LightID lightId, const glm::vec4& eyePosRadius, +bool scanLightVolume(const FrustumGrid& grid, const FrustumGrid::Planes planes[3], int zMin, int zMax, int yMin, int yMax, int xMin, int xMax, LightClusters::LightID lightId, const glm::vec4& eyePosRadius, uint32_t& numClustersTouched, int maxNumIndices, std::vector< std::vector>& clusterGrid) { glm::ivec3 gridPosToOffset(1, grid.dims.x, grid.dims.x * grid.dims.y); @@ -261,7 +281,7 @@ void LightClusters::updateClusters() { } // now voxelize - bool hasBudget = scanLightVolume(theFrustumGrid, zMin, zMax, yMin, yMax, xMin, xMax, lightId, glm::vec4(glm::vec3(eyeOri), radius), numClusterTouched, maxNumIndices, clusterGrid); + bool hasBudget = scanLightVolume(theFrustumGrid, _gridPlanes, zMin, zMax, yMin, yMax, xMin, xMax, lightId, glm::vec4(glm::vec3(eyeOri), radius), numClusterTouched, maxNumIndices, clusterGrid); if (!hasBudget) { break; diff --git a/libraries/render-utils/src/LightClusters.h b/libraries/render-utils/src/LightClusters.h index e5d0275d85..9cafd6b186 100644 --- a/libraries/render-utils/src/LightClusters.h +++ b/libraries/render-utils/src/LightClusters.h @@ -50,8 +50,13 @@ public: #define frustumGrid (*this) #include "LightClusterGrid_shared.slh" + + using Planes = std::vector < glm::vec4 >; + void generateGridPlanes(Planes& xPlanes, Planes& yPlanes, Planes& zPlanes); }; + + class LightClusters { public: using LightID = LightStage::Index; @@ -78,6 +83,8 @@ public: gpu::StructBuffer _frustumGridBuffer; + FrustumGrid::Planes _gridPlanes[3]; + LightStage::LightIndices _visibleLightIndices; gpu::BufferView _lightIndicesBuffer; @@ -90,6 +97,9 @@ public: std::vector _clusterContent; gpu::BufferView _clusterGridBuffer; gpu::BufferView _clusterContentBuffer; + + + }; using LightClustersPointer = std::shared_ptr; diff --git a/libraries/render-utils/src/lightClusters_drawClusterContent.slv b/libraries/render-utils/src/lightClusters_drawClusterContent.slv index d146d8b691..616171b775 100644 --- a/libraries/render-utils/src/lightClusters_drawClusterContent.slv +++ b/libraries/render-utils/src/lightClusters_drawClusterContent.slv @@ -1,4 +1,4 @@ -<@include gpu / Config.slh@> +<@include gpu/Config.slh@> <$VERSION_HEADER$> // Generated on <$_SCRIBE_DATE$> // @@ -12,12 +12,12 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -<@include gpu / Transform.slh@> +<@include gpu/Transform.slh@> <$declareStandardTransform()$> <@include LightClusterGrid.slh@> -<@include gpu / Color.slh@> +<@include gpu/Color.slh@> <$declareColorWheel()$> From f789f566e0eafb06e30825bfc678019c8f4b5bb3 Mon Sep 17 00:00:00 2001 From: samcake Date: Wed, 14 Sep 2016 17:34:17 -0700 Subject: [PATCH 37/75] Minor fix for compilation --- libraries/render-utils/src/LightClusters.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/render-utils/src/LightClusters.cpp b/libraries/render-utils/src/LightClusters.cpp index cbea9a2a2a..78fc7035a4 100644 --- a/libraries/render-utils/src/LightClusters.cpp +++ b/libraries/render-utils/src/LightClusters.cpp @@ -145,7 +145,7 @@ void LightClusters::updateLightFrame(const LightStage::Frame& lightFrame, bool p } bool scanLightVolume(const FrustumGrid& grid, const FrustumGrid::Planes planes[3], int zMin, int zMax, int yMin, int yMax, int xMin, int xMax, LightClusters::LightID lightId, const glm::vec4& eyePosRadius, - uint32_t& numClustersTouched, int maxNumIndices, std::vector< std::vector>& clusterGrid) { + uint32_t& numClustersTouched, uint32_t maxNumIndices, std::vector< std::vector>& clusterGrid) { glm::ivec3 gridPosToOffset(1, grid.dims.x, grid.dims.x * grid.dims.y); bool hasBudget = true; From 3616a6fc12e2632c916f55b51d8eeca1086031bf Mon Sep 17 00:00:00 2001 From: samcake Date: Wed, 14 Sep 2016 19:13:53 -0700 Subject: [PATCH 38/75] Startign implementing the tighter culling for sphere but not done yet --- .../src/LightClusterGrid_shared.slh | 8 ++- libraries/render-utils/src/LightClusters.cpp | 61 +++++++++++++++++-- 2 files changed, 63 insertions(+), 6 deletions(-) diff --git a/libraries/render-utils/src/LightClusterGrid_shared.slh b/libraries/render-utils/src/LightClusterGrid_shared.slh index da4931a91e..b124798131 100644 --- a/libraries/render-utils/src/LightClusterGrid_shared.slh +++ b/libraries/render-utils/src/LightClusterGrid_shared.slh @@ -68,9 +68,9 @@ int frustumGrid_numClusters() { return frustumGrid.dims.x * frustumGrid.dims.y * (frustumGrid.dims.z + 1); } -vec3 frustumGrid_clusterPosToEye(ivec3 clusterPos, vec3 offset) { +vec3 frustumGrid_clusterPosToEye(vec3 clusterPos) { - vec3 cvpos = vec3(clusterPos) + offset; + vec3 cvpos = clusterPos; vec3 volumePos = frustumGrid_gridToVolume(cvpos, frustumGrid.dims); @@ -80,6 +80,10 @@ vec3 frustumGrid_clusterPosToEye(ivec3 clusterPos, vec3 offset) { return eyePos; } +vec3 frustumGrid_clusterPosToEye(ivec3 clusterPos, vec3 offset) { + vec3 cvpos = vec3(clusterPos) + offset; + return frustumGrid_clusterPosToEye(cvpos); +} int frustumGrid_eyeDepthToClusterLayer(float eyeZ) { if ((eyeZ > -frustumGrid.frustumNear) || (eyeZ < -frustumGrid.frustumFar)) { diff --git a/libraries/render-utils/src/LightClusters.cpp b/libraries/render-utils/src/LightClusters.cpp index 78fc7035a4..09061e8dc6 100644 --- a/libraries/render-utils/src/LightClusters.cpp +++ b/libraries/render-utils/src/LightClusters.cpp @@ -46,15 +46,26 @@ void FrustumGrid::generateGridPlanes(Planes& xPlanes, Planes& yPlanes, Planes& z yPlanes.resize(dims.y + 1); zPlanes.resize(dims.z + 1); + float centerY = float(dims.y) * 0.5; + float centerX = float(dims.x) * 0.5; - for (int z = 0; z < xPlanes.size(); z++) { + for (int z = 0; z < zPlanes.size(); z++) { ivec3 pos(0, 0, z); zPlanes[z] = glm::vec4(0.0f, 0.0f, -1.0f, frustumGrid_clusterPosToEye(pos, vec3(0.0)).z); } for (int x = 0; x < xPlanes.size(); x++) { - + auto slicePos = frustumGrid_clusterPosToEye(glm::vec3((float)x, centerY, 0.0)); + auto sliceDir = glm::normalize(slicePos); + xPlanes[x] = glm::vec4(sliceDir.z, 0.0, -sliceDir.x, 0.0); } + + for (int y = 0; y < yPlanes.size(); y++) { + auto slicePos = frustumGrid_clusterPosToEye(glm::vec3(centerX, (float)y, 0.0)); + auto sliceDir = glm::normalize(slicePos); + yPlanes[y] = glm::vec4(0.0, sliceDir.z, -sliceDir.x, 0.0); + } + } #include "DeferredLightingEffect.h" @@ -144,14 +155,42 @@ void LightClusters::updateLightFrame(const LightStage::Frame& lightFrame, bool p _lightIndicesBuffer._size = _visibleLightIndices.size() * sizeof(int); } +glm::vec4 projectToPlane(glm::vec4& sphere, const glm::vec4& plane) { + float distance = sphere.x * plane.x + sphere.y *plane.y + sphere.z * plane.z + plane.w; + + if (distance < sphere.w) { + return glm::vec4(sphere.x - distance * plane.x, sphere.y - distance * plane.y, sphere.z - distance * plane.z, sqrt(sphere.w * sphere.w - distance * distance)); + } else { + return sphere; + } +} + bool scanLightVolume(const FrustumGrid& grid, const FrustumGrid::Planes planes[3], int zMin, int zMax, int yMin, int yMax, int xMin, int xMax, LightClusters::LightID lightId, const glm::vec4& eyePosRadius, uint32_t& numClustersTouched, uint32_t maxNumIndices, std::vector< std::vector>& clusterGrid) { glm::ivec3 gridPosToOffset(1, grid.dims.x, grid.dims.x * grid.dims.y); + int center_z = (zMax + zMin) >> 1; + int center_y = (yMax + yMin) >> 1; bool hasBudget = true; for (auto z = zMin; (z <= zMax) && hasBudget; z++) { + auto zSphere = eyePosRadius; + if (z != center_z) { + auto& plane = (z < center_z) ? planes[2][z + 1] : -planes[2][z]; + zSphere = projectToPlane(zSphere, plane); + } for (auto y = yMin; (y <= yMax) && hasBudget; y++) { - for (auto x = xMin; (x <= xMax) && hasBudget; x++) { + auto ySphere = zSphere; + if (y != center_y) { + auto& plane = (y < center_y) ? planes[1][y + 1] : -planes[1][y]; + ySphere = projectToPlane(ySphere, plane); + } + + auto x = xMin; + do { ++x; } while ((x < xMax) && (glm::dot(planes[0][x], glm::vec4(ySphere.x, ySphere.y, ySphere.z, 1.0)) >= ySphere.w)); + auto xs = xMax; + do { --xs; } while ((xs >= x) && (-glm::dot(planes[0][xs], glm::vec4(ySphere.x, ySphere.y, ySphere.z, 1.0)) >= ySphere.w)); + + for (--x; (x <= xs) && hasBudget; x++) { auto index = x + gridPosToOffset.y * y + gridPosToOffset.z * z; clusterGrid[index].emplace_back(lightId); numClustersTouched++; @@ -281,7 +320,21 @@ void LightClusters::updateClusters() { } // now voxelize - bool hasBudget = scanLightVolume(theFrustumGrid, _gridPlanes, zMin, zMax, yMin, yMax, xMin, xMax, lightId, glm::vec4(glm::vec3(eyeOri), radius), numClusterTouched, maxNumIndices, clusterGrid); + // bool hasBudget = scanLightVolume(theFrustumGrid, _gridPlanes, zMin, zMax, yMin, yMax, xMin, xMax, lightId, glm::vec4(glm::vec3(eyeOri), radius), numClusterTouched, maxNumIndices, clusterGrid); + + bool hasBudget = true; + for (auto z = zMin; (z <= zMax) && hasBudget; z++) { + for (auto y = yMin; (y <= yMax) && hasBudget; y++) { + for (auto x = xMin; (x <= xMax) && hasBudget; x++) { + auto index = x + gridPosToOffset.y * y + gridPosToOffset.z * z; + clusterGrid[index].emplace_back(lightId); + numClusterTouched++; + if (numClusterTouched >= maxNumIndices) { + hasBudget = false; + } + } + } + } if (!hasBudget) { break; From a0862820e692f80420191812af4c61ad094d64fc Mon Sep 17 00:00:00 2001 From: samcake Date: Tue, 27 Sep 2016 18:38:15 -0700 Subject: [PATCH 39/75] MOre refinements? --- .../render-utils/src/LightClusterGrid.slh | 11 -- .../src/LightClusterGrid_shared.slh | 43 ++++-- libraries/render-utils/src/LightClusters.cpp | 122 +++++++++++------- libraries/render-utils/src/LightClusters.h | 8 +- .../src/lightClusters_drawClusterContent.slv | 2 +- .../lightClusters_drawClusterFromDepth.slf | 2 +- .../lightClusters_drawClusterFromDepth.slv | 10 +- .../src/lightClusters_drawGrid.slv | 2 +- .../render-utils/src/local_lights_shading.slf | 2 +- 9 files changed, 116 insertions(+), 86 deletions(-) diff --git a/libraries/render-utils/src/LightClusterGrid.slh b/libraries/render-utils/src/LightClusterGrid.slh index cd94b49ddd..7964d09142 100644 --- a/libraries/render-utils/src/LightClusterGrid.slh +++ b/libraries/render-utils/src/LightClusterGrid.slh @@ -55,17 +55,6 @@ uniform clusterContentBuffer { int _clusterGridContent[16384]; }; -int clusterGrid_clusterToIndex(ivec3 pos) { - return pos.x + (pos.y + pos.z * frustumGrid.dims.y) * frustumGrid.dims.x; -} -ivec3 clusterGrid_indexToCluster(int index) { - ivec3 summedDims = ivec3(frustumGrid.dims.x * frustumGrid.dims.y, frustumGrid.dims.x, 1); - int layer = index / summedDims.x; - int offsetInLayer = index % summedDims.x; - ivec3 clusterPos = ivec3(offsetInLayer % summedDims.y, offsetInLayer / summedDims.y, layer); - return clusterPos; -} - ivec2 clusterGrid_getCluster(int index) { int clusterDesc = _clusterGridTable[index]; int numLights = 0xFFFF & (clusterDesc >> 16); diff --git a/libraries/render-utils/src/LightClusterGrid_shared.slh b/libraries/render-utils/src/LightClusterGrid_shared.slh index b124798131..54281d010e 100644 --- a/libraries/render-utils/src/LightClusterGrid_shared.slh +++ b/libraries/render-utils/src/LightClusterGrid_shared.slh @@ -1,27 +1,33 @@ // glsl / C++ compatible source as interface for FrustrumGrid -float frustumGrid_depthRamp(float linear) { - // return linear; - return linear * linear; +float frustumGrid_depthRampGridToVolume(float ngrid) { + if (ngrid < 0.0) + return ngrid; + // return ngrid; + // return sqrt(ngrid); + return exp2(ngrid) - 1.0; } -float frustumGrid_depthRampInverse(float volume) { - // return volume; - return sqrt(volume); +float frustumGrid_depthRampInverseVolumeToGrid(float nvolume) { + if (nvolume < 0.0) + return nvolume; + // return nvolume; + // return nvolume * nvolume; + return log2(nvolume + 1.0); } vec3 frustumGrid_gridToVolume(vec3 pos, ivec3 dims) { vec3 gridScale = vec3(1.0, 1.0, 1.0) / vec3(dims); vec3 volumePos = pos * gridScale; - volumePos.z = frustumGrid_depthRamp(volumePos.z); + volumePos.z = frustumGrid_depthRampGridToVolume(volumePos.z); return volumePos; } float frustumGrid_volumeToGridDepth(float vposZ, ivec3 dims) { - return frustumGrid_depthRampInverse(vposZ) * float(dims.z); + return frustumGrid_depthRampInverseVolumeToGrid(vposZ) * float(dims.z); } vec3 frustumGrid_volumeToGrid(vec3 vpos, ivec3 dims) { - vec3 gridPos = vec3(vpos.x, vpos.y, frustumGrid_depthRampInverse(vpos.z)) * vec3(dims); + vec3 gridPos = vec3(vpos.x, vpos.y, frustumGrid_depthRampInverseVolumeToGrid(vpos.z)) * vec3(dims); return gridPos; } @@ -68,6 +74,21 @@ int frustumGrid_numClusters() { return frustumGrid.dims.x * frustumGrid.dims.y * (frustumGrid.dims.z + 1); } +int frustumGrid_clusterToIndex(ivec3 pos) { + return pos.x + (pos.y + pos.z * frustumGrid.dims.y) * frustumGrid.dims.x; +} +ivec3 frustumGrid_indexToCluster(int index) { + if (index <= 0) { + return ivec3(0, 0, -1); + } + index -= 1; + ivec3 summedDims = ivec3(frustumGrid.dims.x * frustumGrid.dims.y, frustumGrid.dims.x, 1); + int layer = index / summedDims.x; + int offsetInLayer = index % summedDims.x; + ivec3 clusterPos = ivec3(offsetInLayer % summedDims.y, offsetInLayer / summedDims.y, layer); + return clusterPos; +} + vec3 frustumGrid_clusterPosToEye(vec3 clusterPos) { vec3 cvpos = clusterPos; @@ -87,7 +108,7 @@ vec3 frustumGrid_clusterPosToEye(ivec3 clusterPos, vec3 offset) { int frustumGrid_eyeDepthToClusterLayer(float eyeZ) { if ((eyeZ > -frustumGrid.frustumNear) || (eyeZ < -frustumGrid.frustumFar)) { - return -1; + return -2; } if (eyeZ > -frustumGrid.rangeNear) { @@ -108,7 +129,7 @@ int frustumGrid_eyeDepthToClusterLayer(float eyeZ) { ivec3 frustumGrid_eyeToClusterPos(vec3 eyePos) { if ((eyePos.z > -frustumGrid.frustumNear) || (eyePos.z < -frustumGrid.frustumFar)) { - return ivec3(-1); + return ivec3(-2); } if (eyePos.z > -frustumGrid.rangeNear) { diff --git a/libraries/render-utils/src/LightClusters.cpp b/libraries/render-utils/src/LightClusters.cpp index 362e6c3665..651ba4957d 100644 --- a/libraries/render-utils/src/LightClusters.cpp +++ b/libraries/render-utils/src/LightClusters.cpp @@ -49,18 +49,18 @@ void FrustumGrid::generateGridPlanes(Planes& xPlanes, Planes& yPlanes, Planes& z float centerY = float(dims.y) * 0.5; float centerX = float(dims.x) * 0.5; - for (int z = 0; z < zPlanes.size(); z++) { + for (int z = 0; z < (int) zPlanes.size(); z++) { ivec3 pos(0, 0, z); zPlanes[z] = glm::vec4(0.0f, 0.0f, 1.0f, -frustumGrid_clusterPosToEye(pos, vec3(0.0)).z); } - for (int x = 0; x < xPlanes.size(); x++) { + for (int x = 0; x < (int) xPlanes.size(); x++) { auto slicePos = frustumGrid_clusterPosToEye(glm::vec3((float)x, centerY, 0.0)); auto sliceDir = glm::normalize(slicePos); xPlanes[x] = glm::vec4(sliceDir.z, 0.0, -sliceDir.x, 0.0); } - for (int y = 0; y < yPlanes.size(); y++) { + for (int y = 0; y < (int) yPlanes.size(); y++) { auto slicePos = frustumGrid_clusterPosToEye(glm::vec3(centerX, (float)y, 0.0)); auto sliceDir = glm::normalize(slicePos); yPlanes[y] = glm::vec4(0.0, sliceDir.z, -sliceDir.y, 0.0); @@ -177,72 +177,95 @@ void LightClusters::updateLightFrame(const LightStage::Frame& lightFrame, bool p } float distanceToPlane(const glm::vec3& point, const glm::vec4& plane) { - return glm::dot(plane, glm::vec4(point.x, point.y, point.z, -1.0)); + return plane.x * point.x + plane.y * point.y + plane.z * point.z + plane.w; } -glm::vec4 projectToPlane(glm::vec4& sphere, const glm::vec4& plane) { +bool reduceSphereToPlane(const glm::vec4& sphere, const glm::vec4& plane, glm::vec4& reducedSphere) { float distance = distanceToPlane(glm::vec3(sphere), plane); - if (distance < sphere.w) { - return glm::vec4(sphere.x - distance * plane.x, sphere.y - distance * plane.y, sphere.z - distance * plane.z, sqrt(sphere.w * sphere.w - distance * distance)); - } else { - return sphere; + if (abs(distance) <= sphere.w) { + reducedSphere = glm::vec4(sphere.x - distance * plane.x, sphere.y - distance * plane.y, sphere.z - distance * plane.z, sqrt(sphere.w * sphere.w - distance * distance)); + return true; } + + return false; } -bool scanLightVolume(const FrustumGrid& grid, const FrustumGrid::Planes planes[3], int zMin, int zMax, int yMin, int yMax, int xMin, int xMax, LightClusters::LightID lightId, const glm::vec4& eyePosRadius, - uint32_t& numClustersTouched, uint32_t maxNumIndices, std::vector< std::vector>& clusterGrid) { +uint32_t scanLightVolumeBox(FrustumGrid& grid, const FrustumGrid::Planes planes[3], int zMin, int zMax, int yMin, int yMax, int xMin, int xMax, LightClusters::LightID lightId, const glm::vec4& eyePosRadius, + std::vector< std::vector>& clusterGrid) { glm::ivec3 gridPosToOffset(1, grid.dims.x, grid.dims.x * grid.dims.y); + uint32_t numClustersTouched = 0; + for (auto z = zMin; (z <= zMax); z++) { + for (auto y = yMin; (y <= yMax); y++) { + for (auto x = xMin; (x <= xMax); x++) { + auto index = 1 + x + gridPosToOffset.y * y + gridPosToOffset.z * z; + clusterGrid[index].emplace_back(lightId); + numClustersTouched++; + } + } + } + + return numClustersTouched; +} + +uint32_t scanLightVolumeSphere(FrustumGrid& grid, const FrustumGrid::Planes planes[3], int zMin, int zMax, int yMin, int yMax, int xMin, int xMax, LightClusters::LightID lightId, const glm::vec4& eyePosRadius, + std::vector< std::vector>& clusterGrid) { + glm::ivec3 gridPosToOffset(1, grid.dims.x, grid.dims.x * grid.dims.y); + uint32_t numClustersTouched = 0; const auto& xPlanes = planes[0]; const auto& yPlanes = planes[1]; const auto& zPlanes = planes[2]; - int center_z = (zMax + zMin) >> 1; + int center_z = grid.frustumGrid_eyeDepthToClusterLayer(eyePosRadius.z); int center_y = (yMax + yMin) >> 1; - bool hasBudget = true; - for (auto z = zMin; (z <= zMax) && hasBudget; z++) { + for (auto z = zMin; (z <= zMax); z++) { auto zSphere = eyePosRadius; if (z != center_z) { auto& plane = (z < center_z) ? zPlanes[z + 1] : -zPlanes[z]; - zSphere = projectToPlane(zSphere, plane); + if (!reduceSphereToPlane(zSphere, plane, zSphere)) { + // pass this slice! + continue; + } } - for (auto y = yMin; (y <= yMax) && hasBudget; y++) { + for (auto y = yMin; (y <= yMax); y++) { auto ySphere = zSphere; if (y != center_y) { auto& plane = (y < center_y) ? yPlanes[y + 1] : -yPlanes[y]; - ySphere = projectToPlane(ySphere, plane); + if (!reduceSphereToPlane(ySphere, plane, ySphere)) { + // pass this slice! + continue; + } } + glm::vec3 spherePoint(ySphere); + auto x = xMin; for (; (x < xMax); ++x) { auto& plane = xPlanes[x + 1]; - auto testDistance = glm::dot(plane, glm::vec4(ySphere.x, ySphere.y, ySphere.z, -1.0)) + ySphere.w; - if (testDistance >= 0.0f ) { + auto testDistance = distanceToPlane(spherePoint, plane) + ySphere.w; + if (testDistance >= 0.0f) { break; } } auto xs = xMax; for (; (xs >= x); --xs) { auto& plane = -xPlanes[xs]; - auto testDistance = glm::dot(plane, glm::vec4(ySphere.x, ySphere.y, ySphere.z, -1.0)) + ySphere.w; + auto testDistance = distanceToPlane(spherePoint, plane) + ySphere.w; if (testDistance >= 0.0f) { break; } } - for (; (x <= xs) && hasBudget; x++) { - auto index = x + gridPosToOffset.y * y + gridPosToOffset.z * z; + for (; (x <= xs); x++) { + auto index = grid.frustumGrid_clusterToIndex(ivec3(x, y, z)); clusterGrid[index].emplace_back(lightId); numClustersTouched++; - if (numClustersTouched >= maxNumIndices) { - hasBudget = false; - } } } } - return hasBudget; + return numClustersTouched; } void LightClusters::updateClusters() { @@ -284,7 +307,18 @@ void LightClusters::updateClusters() { int zMin = theFrustumGrid.frustumGrid_eyeDepthToClusterLayer(eyeZMin); int zMax = theFrustumGrid.frustumGrid_eyeDepthToClusterLayer(eyeZMax); // That should never happen - if (zMin == -1 && zMax == -1) { + if (zMin == -2 && zMax == -2) { + continue; + } + + // Firt slice volume ? + /* if (zMin == -1) { + clusterGrid[0].emplace_back(lightId); + numClusterTouched++; + } */ + + // Stop there with this light if zmax is in near range + if (zMax == -1) { continue; } @@ -361,37 +395,31 @@ void LightClusters::updateClusters() { } // now voxelize - bool hasBudget = scanLightVolume(theFrustumGrid, _gridPlanes, zMin, zMax, yMin, yMax, xMin, xMax, lightId, glm::vec4(glm::vec3(eyeOri), radius), numClusterTouched, maxNumIndices, clusterGrid); - - /* bool hasBudget = true; - for (auto z = zMin; (z <= zMax) && hasBudget; z++) { - for (auto y = yMin; (y <= yMax) && hasBudget; y++) { - for (auto x = xMin; (x <= xMax) && hasBudget; x++) { - auto index = x + gridPosToOffset.y * y + gridPosToOffset.z * z; - clusterGrid[index].emplace_back(lightId); - numClusterTouched++; - if (numClusterTouched >= maxNumIndices) { - hasBudget = false; - } - } - } - }*/ - - if (!hasBudget) { - break; - } + numClusterTouched += scanLightVolumeSphere(theFrustumGrid, _gridPlanes, zMin, zMax, yMin, yMax, xMin, xMax, lightId, glm::vec4(glm::vec3(eyeOri), radius), clusterGrid); } // Lights have been gathered now reexpress in terms of 2 sequential buffers - + // Start filling from near to far and stops if it overflows + bool checkBudget = false; + if (numClusterTouched > maxNumIndices) { + checkBudget = true; + } uint16_t indexOffset = 0; for (int i = 0; i < clusterGrid.size(); i++) { auto& cluster = clusterGrid[i]; uint16_t numLights = ((uint16_t)cluster.size()); uint16_t offset = indexOffset; + // Check for overflow + if (checkBudget) { + if (indexOffset + numLights > maxNumIndices) { + break; + } + } + _clusterGrid[i] = (uint32_t)((numLights << 16) | offset); + if (numLights) { memcpy(_clusterContent.data() + indexOffset, cluster.data(), numLights * sizeof(LightIndex)); } diff --git a/libraries/render-utils/src/LightClusters.h b/libraries/render-utils/src/LightClusters.h index 88583da31e..02ea436718 100644 --- a/libraries/render-utils/src/LightClusters.h +++ b/libraries/render-utils/src/LightClusters.h @@ -89,7 +89,7 @@ public: LightStage::LightIndices _visibleLightIndices; gpu::BufferView _lightIndicesBuffer; - uint32_t _numClusters { 0 }; + int32_t _numClusters { 0 }; const uint32_t EMPTY_CLUSTER { 0x0000FFFF }; const LightID INVALID_LIGHT { LightStage::INVALID_INDEX }; @@ -124,9 +124,9 @@ public: float rangeNear{ 1.0f }; float rangeFar{ 512.0f }; - int dimX { 8 }; - int dimY { 8 }; - int dimZ { 12 }; + int dimX { 16 }; + int dimY { 16 }; + int dimZ { 16 }; bool freeze{ false }; diff --git a/libraries/render-utils/src/lightClusters_drawClusterContent.slv b/libraries/render-utils/src/lightClusters_drawClusterContent.slv index 616171b775..5bf6a0bf18 100644 --- a/libraries/render-utils/src/lightClusters_drawClusterContent.slv +++ b/libraries/render-utils/src/lightClusters_drawClusterContent.slv @@ -58,7 +58,7 @@ void main(void) { float numLightsScale = clamp(numLights * 0.1, 0.0, 1.0); - ivec3 clusterPos = clusterGrid_indexToCluster(gl_InstanceID); + ivec3 clusterPos = frustumGrid_indexToCluster(gl_InstanceID); float boxScale = 0.99; vec3 eyePos = frustumGrid_clusterPosToEye(clusterPos, vec3((1.0 - boxScale) * 0.5 + (1.0 - numLightsScale) * boxScale * 0.5) + numLightsScale * boxScale * pos.xyz); diff --git a/libraries/render-utils/src/lightClusters_drawClusterFromDepth.slf b/libraries/render-utils/src/lightClusters_drawClusterFromDepth.slf index e711c6fc64..1820d3113b 100644 --- a/libraries/render-utils/src/lightClusters_drawClusterFromDepth.slf +++ b/libraries/render-utils/src/lightClusters_drawClusterFromDepth.slf @@ -37,7 +37,7 @@ void main(void) { ivec3 clusterPos = frustumGrid_eyeToClusterPos(clusterEyePos.xyz); - ivec2 cluster = clusterGrid_getCluster(clusterGrid_clusterToIndex(clusterPos)); + ivec2 cluster = clusterGrid_getCluster(frustumGrid_clusterToIndex(clusterPos)); int numLights = cluster.x; float numLightsScale = clamp(numLights * 0.1, 0.01, 1.0); diff --git a/libraries/render-utils/src/lightClusters_drawClusterFromDepth.slv b/libraries/render-utils/src/lightClusters_drawClusterFromDepth.slv index fa082d880f..93fd13b2f5 100644 --- a/libraries/render-utils/src/lightClusters_drawClusterFromDepth.slv +++ b/libraries/render-utils/src/lightClusters_drawClusterFromDepth.slv @@ -53,15 +53,7 @@ void main(void) { ); vec4 pos = UNIT_BOX[UNIT_BOX_LINE_INDICES[gl_VertexID]]; - ivec3 dims = frustumGrid.dims.xyz; - - ivec3 summedDims = ivec3(dims.x * dims.y, dims.x, 1); - - int layer = gl_InstanceID / summedDims.x; - int offsetInLayer = gl_InstanceID % summedDims.x; - ivec3 clusterPos = ivec3(offsetInLayer % summedDims.y, offsetInLayer / summedDims.y, layer); - - + ivec3 clusterPos = frustumGrid_indexToCluster(gl_InstanceID); vec3 eyePos = frustumGrid_clusterPosToEye(clusterPos, vec3(0.05) + 0.9 * pos.xyz); vec4 worldPos = frustumGrid_eyeToWorld(vec4(eyePos.xyz, 1.0)); diff --git a/libraries/render-utils/src/lightClusters_drawGrid.slv b/libraries/render-utils/src/lightClusters_drawGrid.slv index 0eec0d04ee..15fa8ac38a 100644 --- a/libraries/render-utils/src/lightClusters_drawGrid.slv +++ b/libraries/render-utils/src/lightClusters_drawGrid.slv @@ -57,7 +57,7 @@ void main(void) { ivec2 cluster = clusterGrid_getCluster(gl_InstanceID); int numLights = cluster.x; - ivec3 clusterPos = clusterGrid_indexToCluster(gl_InstanceID); + ivec3 clusterPos = frustumGrid_indexToCluster(gl_InstanceID); float boxScale = 1.0; diff --git a/libraries/render-utils/src/local_lights_shading.slf b/libraries/render-utils/src/local_lights_shading.slf index 2b8beb67c3..eba65c39af 100644 --- a/libraries/render-utils/src/local_lights_shading.slf +++ b/libraries/render-utils/src/local_lights_shading.slf @@ -61,7 +61,7 @@ void main(void) { ivec3 clusterPos = frustumGrid_eyeToClusterPos(clusterEyePos.xyz); - ivec2 cluster = clusterGrid_getCluster(clusterGrid_clusterToIndex(clusterPos)); + ivec2 cluster = clusterGrid_getCluster(frustumGrid_clusterToIndex(clusterPos)); int numLights = cluster.x; if (numLights <= 0) { discard; From cd9dff57bed1fd48cc1c7c093dc0a5411f9ab680 Mon Sep 17 00:00:00 2001 From: samcake Date: Wed, 28 Sep 2016 10:03:51 -0700 Subject: [PATCH 40/75] back to normal --- libraries/render-utils/src/LightClusterGrid_shared.slh | 4 ---- 1 file changed, 4 deletions(-) diff --git a/libraries/render-utils/src/LightClusterGrid_shared.slh b/libraries/render-utils/src/LightClusterGrid_shared.slh index 54281d010e..ec27b11a3f 100644 --- a/libraries/render-utils/src/LightClusterGrid_shared.slh +++ b/libraries/render-utils/src/LightClusterGrid_shared.slh @@ -78,10 +78,6 @@ int frustumGrid_clusterToIndex(ivec3 pos) { return pos.x + (pos.y + pos.z * frustumGrid.dims.y) * frustumGrid.dims.x; } ivec3 frustumGrid_indexToCluster(int index) { - if (index <= 0) { - return ivec3(0, 0, -1); - } - index -= 1; ivec3 summedDims = ivec3(frustumGrid.dims.x * frustumGrid.dims.y, frustumGrid.dims.x, 1); int layer = index / summedDims.x; int offsetInLayer = index % summedDims.x; From b09151f2a22a5cfcf188cae47e0e9374a73b77eb Mon Sep 17 00:00:00 2001 From: samcake Date: Wed, 28 Sep 2016 18:32:35 -0700 Subject: [PATCH 41/75] Rearrange the light struc description in the shader side, needs the c++ to match now --- libraries/model/src/model/Light.h | 38 ++++ libraries/model/src/model/Light.slh | 197 ++++++------------ .../render-utils/src/DeferredGlobalLight.slh | 22 +- libraries/render-utils/src/LightAmbient.slh | 18 +- .../render-utils/src/LightDirectional.slh | 6 +- libraries/render-utils/src/LightPoint.slh | 4 +- libraries/render-utils/src/LightSpot.slh | 6 +- .../render-utils/src/deferred_light_point.slv | 2 +- .../render-utils/src/deferred_light_spot.slv | 2 +- .../render-utils/src/local_lights_shading.slf | 13 +- libraries/render-utils/src/overlay3D.slf | 10 +- .../src/overlay3D_translucent.slf | 10 +- libraries/render-utils/src/point_light.slf | 2 +- 13 files changed, 166 insertions(+), 164 deletions(-) diff --git a/libraries/model/src/model/Light.h b/libraries/model/src/model/Light.h index c091026ba2..f1c68bb93a 100755 --- a/libraries/model/src/model/Light.h +++ b/libraries/model/src/model/Light.h @@ -26,8 +26,46 @@ typedef glm::vec3 Vec3; typedef glm::vec4 Vec4; typedef glm::quat Quat; + class Light { public: + + struct LightVolume { + vec3 position; + float radius; + vec3 direction; + float spotCos; + + bool isPoint() { return bool(spotCos < 0.f); } + bool isSpot() { return bool(spotCos >= 0.f); } + + vec3 getPosition() { return position; } + float getRadius() { return radius; } + float getRadiusSquare() { return radius * radius; } + vec3 getDirection() { return direction; } + + float getSpotAngleCos() { return spotCos; } + }; + + + struct LightIrradiance { + vec3 color; + float intensity; + float falloffRadius; + float falloffSpot; + float spare1; + float spare2; + + vec3 getColor() { return color; } + float getIntensity() { return intensity; } + vec3 getIrradiance() { return color * intensity; } + float getFalloffRadius() { return falloffRadius; } + float getFalloffRadiusSquare() { return falloffRadius * falloffRadius; } + float getFalloffSpot() { return falloffSpot; } + }; + + + enum Type { SUN = 0, POINT, diff --git a/libraries/model/src/model/Light.slh b/libraries/model/src/model/Light.slh index 888abf5038..6e9f92e67f 100644 --- a/libraries/model/src/model/Light.slh +++ b/libraries/model/src/model/Light.slh @@ -11,129 +11,74 @@ <@if not MODEL_LIGHT_SLH@> <@def MODEL_LIGHT_SLH@> -struct SphericalHarmonics { - vec4 L00; - vec4 L1m1; - vec4 L10; - vec4 L11; - vec4 L2m2; - vec4 L2m1; - vec4 L20; - vec4 L21; - vec4 L22; -}; +<@include model/SphericalHarmonics.shared.slh@> +<@include model/LightVolume.shared.slh@> +<@include model/LightIrradiance.shared.slh@> -vec4 evalSphericalLight(SphericalHarmonics sh, vec3 direction ) { - - vec3 dir = direction.xyz; - - const float C1 = 0.429043; - const float C2 = 0.511664; - const float C3 = 0.743125; - const float C4 = 0.886227; - const float C5 = 0.247708; - - vec4 value = C1 * sh.L22 * (dir.x * dir.x - dir.y * dir.y) + - C3 * sh.L20 * dir.z * dir.z + - C4 * sh.L00 - C5 * sh.L20 + - 2.0 * C1 * ( sh.L2m2 * dir.x * dir.y + - sh.L21 * dir.x * dir.z + - sh.L2m1 * dir.y * dir.z ) + - 2.0 * C2 * ( sh.L11 * dir.x + - sh.L1m1 * dir.y + - sh.L10 * dir.z ) ; - return value; -} +// NOw lets define Light struct Light { - vec4 _position; - vec4 _direction; - vec4 _color; - vec4 _attenuation; - vec4 _spot; - - // vec4 _shadow; - vec4 _control; - - vec4 _volumeGeometry; - - SphericalHarmonics _ambientSphere; + LightVolume volume; + LightIrradiance irradiance; }; -const int LIGHT_SPOT = 2; - -bool light_isSpot(Light l) { - return bool(l._control.y >= 2.f); -} - -vec3 getLightPosition(Light l) { return l._position.xyz; } -vec3 getLightDirection(Light l) { return l._direction.xyz; } // direction is -Z axis - -vec3 getLightColor(Light l) { return l._color.rgb; } -float getLightIntensity(Light l) { return l._color.w; } -float getLightAmbientIntensity(Light l) { return l._direction.w; } - -float getLightSpotAngleCos(Light l) { - return l._spot.x; -} - -vec2 getLightSpotOutsideNormal2(Light l) { - return vec2(-l._spot.y, l._spot.x); -} - -float evalLightSpotAttenuation(Light l, float cosA) { - return pow(cosA, l._spot.w); -} - -float getLightRadius(Light l) { - return l._attenuation.x; -} - -float getLightSquareRadius(Light l) { - return getLightRadius(l) * getLightRadius(l); -} - -float getLightCutoffRadius(Light l) { - return l._attenuation.z; -} - -float getLightCutoffSquareRadius(Light l) { - return getLightCutoffRadius(l) * getLightCutoffRadius(l); -} - -float getLightShowContour(Light l) { - return l._control.w; -} - -vec4 getLightVolumeGeometry(Light l) { - return l._volumeGeometry; -} // Light is the light source its self, d is the light's distance calculated as length(unnormalized light vector). float evalLightAttenuation(Light l, float d) { - float radius = getLightRadius(l); + float radius = lightIrradiance_getFalloffRadius(l.irradiance); + float cutoff = lightVolume_getRadius(l.volume); float denom = d / radius + 1.0; float attenuation = 1.0 / (denom * denom); - - float cutoff = getLightCutoffRadius(l); - + + // "Fade" the edges of light sources to make things look a bit more attractive. // Note: this tends to look a bit odd at lower exponents. attenuation *= min(1, max(0, -(d - cutoff))); - + return attenuation; } -SphericalHarmonics getLightAmbientSphere(Light l) { + +float evalLightSpotAttenuation(Light l, float cosA) { + return pow(cosA, lightIrradiance_getFalloffSpot(l.irradiance)); +} + +bool light_isSpot(Light l) { return lightVolume_isSpot(l.volume); } + +vec3 getLightPosition(Light l) { return lightVolume_getPosition(l.volume); } +vec3 getLightDirection(Light l) { return lightVolume_getDirection(l.volume); } + + +vec3 getLightColor(Light l) { return lightIrradiance_getColor(l.irradiance); } +float getLightIntensity(Light l) { return lightIrradiance_getIntensity(l.irradiance); } +vec3 getLightIrradiance(Light l) { return lightIrradiance_getIrradiance(l.irradiance); } + + + + + + + +struct LightAmbient { + vec4 _ambient; + SphericalHarmonics _ambientSphere; +}; + +SphericalHarmonics getLightAmbientSphere(LightAmbient l) { return l._ambientSphere; } -bool getLightHasAmbientMap(Light l) { - return l._control.x > 0; + +float getLightAmbientIntensity(LightAmbient l) { return l._ambient.w; } + + +bool getLightHasAmbientMap(LightAmbient l) { + return l._ambient.x > 0; + // return l._control.x > 0; } -float getLightAmbientMapNumMips(Light l) { - return l._control.x; +float getLightAmbientMapNumMips(LightAmbient l) { + return l._ambient.x; } <@func declareLightBuffer(N)@> @@ -146,6 +91,7 @@ uniform lightBuffer { Light getLight(int index) { return lightArray[index]; } + <@else@> uniform lightBuffer { Light light; @@ -161,39 +107,32 @@ Light getLight() { -bool clipFragToLightVolumePoint(Light light, vec3 fragPos, out vec4 fragLightVecLen2) { - fragLightVecLen2.xyz = getLightPosition(light) - fragPos.xyz; - fragLightVecLen2.w = dot(fragLightVecLen2.xyz, fragLightVecLen2.xyz); - // Kill if too far from the light center - if (fragLightVecLen2.w > getLightCutoffSquareRadius(light)) { - return false; - } - return true; + +<@func declareLightAmbientBuffer(N)@> + +<@if N@> + +uniform lightAmbientBuffer { + LightAmbient lightAmbientArray[<$N$>]; +}; + +LightAmbient getLightAmbient(int index) { + return lightAmbientArray[index]; } -bool clipFragToLightVolumeSpot(Light light, vec3 fragPos, out vec4 fragLightVecLen2, out vec4 fragLightDirLen, out float cosSpotAngle) { - fragLightVecLen2.xyz = getLightPosition(light) - fragPos.xyz; - fragLightVecLen2.w = dot(fragLightVecLen2.xyz, fragLightVecLen2.xyz); +<@else@> +uniform lightAmbientBuffer { + LightAmbient lightAmbient; +}; - // Kill if too far from the light center - if (fragLightVecLen2.w > getLightCutoffSquareRadius(light)) { - return false; - } - - // Allright we re valid in the volume - fragLightDirLen.w = length(fragLightVecLen2.xyz); - fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w; - - // Kill if not in the spot light (ah ah !) - cosSpotAngle = max(-dot(fragLightDirLen.xyz, getLightDirection(light)), 0.0); - if (cosSpotAngle < getLightSpotAngleCos(light)) { - return false; - } - - return true; +LightAmbient getLightAmbient() { + return lightAmbient; } +<@endif@> + +<@endfunc@> <@endif@> diff --git a/libraries/render-utils/src/DeferredGlobalLight.slh b/libraries/render-utils/src/DeferredGlobalLight.slh index cb5dd9dc48..76194965c1 100755 --- a/libraries/render-utils/src/DeferredGlobalLight.slh +++ b/libraries/render-utils/src/DeferredGlobalLight.slh @@ -15,6 +15,7 @@ <@include LightingModel.slh@> <$declareLightBuffer()$> +<$declareLightAmbientBuffer()$> <@include LightAmbient.slh@> <@include LightDirectional.slh@> @@ -29,7 +30,11 @@ // Get light Light light = getLight(); + LightAmbient lightAmbient = getLightAmbient(); + vec3 lightDirection = getLightDirection(light); + vec3 lightIrradiance = getLightIrradiance(light); + vec3 color = vec3(0.0); <@endfunc@> @@ -38,7 +43,7 @@ <@func declareEvalAmbientGlobalColor()@> vec3 evalAmbientGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal, vec3 albedo, vec3 fresnel, float metallic, float roughness) { <$prepareGlobalLight()$> - color += albedo * getLightColor(light) * obscurance * getLightAmbientIntensity(light); + color += albedo * getLightColor(light) * obscurance * getLightAmbientIntensity(lightAmbient); return color; } <@endfunc@> @@ -63,7 +68,7 @@ vec3 albedo, vec3 fresnel, float metallic, float roughness // Ambient vec3 ambientDiffuse; vec3 ambientSpecular; - evalLightingAmbient(ambientDiffuse, ambientSpecular, light, fragEyeDir, fragNormal, roughness, metallic, fresnel, albedo, obscurance + evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, fragEyeDir, fragNormal, roughness, metallic, fresnel, albedo, obscurance <@if supportScattering@> ,scattering, midNormalCurvature, lowNormalCurvature <@endif@> ); @@ -74,7 +79,7 @@ vec3 albedo, vec3 fresnel, float metallic, float roughness // Directional vec3 directionalDiffuse; vec3 directionalSpecular; - evalLightingDirectional(directionalDiffuse, directionalSpecular, light, fragEyeDir, fragNormal, roughness, metallic, fresnel, albedo, shadowAttenuation + evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, fragEyeDir, fragNormal, roughness, metallic, fresnel, albedo, shadowAttenuation <@if supportScattering@> ,scattering, midNormalCurvature, lowNormalCurvature <@endif@> ); @@ -107,7 +112,7 @@ vec3 evalSkyboxGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscu // Ambient vec3 ambientDiffuse; vec3 ambientSpecular; - evalLightingAmbient(ambientDiffuse, ambientSpecular, light, fragEyeDir, fragNormal, roughness, metallic, fresnel, albedo, obscurance + evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, fragEyeDir, fragNormal, roughness, metallic, fresnel, albedo, obscurance <@if supportScattering@> ,scattering, midNormalCurvature, lowNormalCurvature <@endif@> @@ -119,7 +124,7 @@ vec3 evalSkyboxGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscu // Directional vec3 directionalDiffuse; vec3 directionalSpecular; - evalLightingDirectional(directionalDiffuse, directionalSpecular, light, fragEyeDir, fragNormal, roughness, metallic, fresnel, albedo, shadowAttenuation + evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, fragEyeDir, fragNormal, roughness, metallic, fresnel, albedo, shadowAttenuation <@if supportScattering@> ,scattering, midNormalCurvature, lowNormalCurvature <@endif@> @@ -135,6 +140,7 @@ vec3 evalSkyboxGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscu <@func declareEvalLightmappedColor()@> vec3 evalLightmappedColor(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 normal, vec3 albedo, vec3 lightmap) { Light light = getLight(); + LightAmbient ambient = getLightAmbient(); // Catch normals perpendicular to the projection plane, hence the magic number for the threshold // It should be just 0, but we have inaccuracy so we overshoot @@ -150,7 +156,7 @@ vec3 evalLightmappedColor(mat4 invViewMat, float shadowAttenuation, float obscur vec3 diffuseLight = lightAttenuation * lightmap; // Ambient light is the lightmap when in shadow - vec3 ambientLight = (1 - lightAttenuation) * lightmap * getLightAmbientIntensity(light); + vec3 ambientLight = (1 - lightAttenuation) * lightmap * getLightAmbientIntensity(ambient); return isLightmapEnabled() * obscurance * albedo * (diffuseLight + ambientLight); } @@ -172,7 +178,7 @@ vec3 evalGlobalLightingAlphaBlended(mat4 invViewMat, float shadowAttenuation, fl // Ambient vec3 ambientDiffuse; vec3 ambientSpecular; - evalLightingAmbient(ambientDiffuse, ambientSpecular, light, fragEyeDir, fragNormal, roughness, metallic, fresnel, albedo, obscurance); + evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, fragEyeDir, fragNormal, roughness, metallic, fresnel, albedo, obscurance); color += ambientDiffuse; color += ambientSpecular / opacity; @@ -180,7 +186,7 @@ vec3 evalGlobalLightingAlphaBlended(mat4 invViewMat, float shadowAttenuation, fl // Directional vec3 directionalDiffuse; vec3 directionalSpecular; - evalLightingDirectional(directionalDiffuse, directionalSpecular, light, fragEyeDir, fragNormal, roughness, metallic, fresnel, albedo, shadowAttenuation); + evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, fragEyeDir, fragNormal, roughness, metallic, fresnel, albedo, shadowAttenuation); color += directionalDiffuse; color += directionalSpecular / opacity; diff --git a/libraries/render-utils/src/LightAmbient.slh b/libraries/render-utils/src/LightAmbient.slh index ec665e6deb..ecb8fa0ae5 100644 --- a/libraries/render-utils/src/LightAmbient.slh +++ b/libraries/render-utils/src/LightAmbient.slh @@ -30,16 +30,16 @@ vec3 fresnelSchlickAmbient(vec3 fresnelColor, vec3 lightDir, vec3 halfDir, float <$declareSkyboxMap()$> <@endif@> -vec3 evalAmbientSpecularIrradiance(Light light, vec3 fragEyeDir, vec3 fragNormal, float roughness, vec3 fresnel) { +vec3 evalAmbientSpecularIrradiance(LightAmbient ambient, vec3 fragEyeDir, vec3 fragNormal, float roughness, vec3 fresnel) { vec3 direction = -reflect(fragEyeDir, fragNormal); vec3 ambientFresnel = fresnelSchlickAmbient(fresnel, fragEyeDir, fragNormal, 1 - roughness); vec3 specularLight; <@if supportIfAmbientMapElseAmbientSphere@> - if (getLightHasAmbientMap(light)) + if (getLightHasAmbientMap(ambient)) <@endif@> <@if supportAmbientMap@> { - float levels = getLightAmbientMapNumMips(light); + float levels = getLightAmbientMapNumMips(ambient); float lod = min(floor((roughness)* levels), levels); specularLight = evalSkyboxLight(direction, lod).xyz; } @@ -49,7 +49,7 @@ vec3 evalAmbientSpecularIrradiance(Light light, vec3 fragEyeDir, vec3 fragNormal <@endif@> <@if supportAmbientSphere@> { - specularLight = evalSphericalLight(getLightAmbientSphere(light), direction).xyz; + specularLight = sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), direction).xyz; } <@endif@> @@ -67,7 +67,7 @@ float curvatureAO(in float k) { } <@endif@> -void evalLightingAmbient(out vec3 diffuse, out vec3 specular, Light light, vec3 eyeDir, vec3 normal, +void evalLightingAmbient(out vec3 diffuse, out vec3 specular, LightAmbient ambient, vec3 eyeDir, vec3 normal, float roughness, float metallic, vec3 fresnel, vec3 albedo, float obscurance <@if supportScattering@> , float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature @@ -76,10 +76,10 @@ void evalLightingAmbient(out vec3 diffuse, out vec3 specular, Light light, vec3 // Diffuse from ambient - diffuse = (1 - metallic) * evalSphericalLight(getLightAmbientSphere(light), normal).xyz; + diffuse = (1 - metallic) * sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), normal).xyz; // Specular highlight from ambient - specular = evalAmbientSpecularIrradiance(light, eyeDir, normal, roughness, fresnel) * obscurance * getLightAmbientIntensity(light); + specular = evalAmbientSpecularIrradiance(ambient, eyeDir, normal, roughness, fresnel) * obscurance * getLightAmbientIntensity(ambient); <@if supportScattering@> @@ -92,7 +92,7 @@ void evalLightingAmbient(out vec3 diffuse, out vec3 specular, Light light, vec3 if (scattering * isScatteringEnabled() > 0.0) { // Diffuse from ambient - diffuse = evalSphericalLight(getLightAmbientSphere(light), lowNormalCurvature.xyz).xyz; + diffuse = sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), lowNormalCurvature.xyz).xyz; specular = vec3(0.0); } @@ -102,7 +102,7 @@ void evalLightingAmbient(out vec3 diffuse, out vec3 specular, Light light, vec3 obscurance = 1.0; } - float lightEnergy = obscurance * getLightAmbientIntensity(light); + float lightEnergy = obscurance * getLightAmbientIntensity(ambient); if (isAlbedoEnabled() > 0.0) { diffuse *= albedo; diff --git a/libraries/render-utils/src/LightDirectional.slh b/libraries/render-utils/src/LightDirectional.slh index 86eb130491..749709c600 100644 --- a/libraries/render-utils/src/LightDirectional.slh +++ b/libraries/render-utils/src/LightDirectional.slh @@ -11,7 +11,7 @@ <@func declareLightingDirectional(supportScattering)@> -void evalLightingDirectional(out vec3 diffuse, out vec3 specular, Light light, +void evalLightingDirectional(out vec3 diffuse, out vec3 specular, vec3 lightDir, vec3 lightIrradiance, vec3 eyeDir, vec3 normal, float roughness, float metallic, vec3 fresnel, vec3 albedo, float shadow <@if supportScattering@> @@ -20,9 +20,9 @@ void evalLightingDirectional(out vec3 diffuse, out vec3 specular, Light light, ) { // Attenuation - vec3 lightEnergy = shadow * getLightColor(light) * getLightIntensity(light); + vec3 lightEnergy = shadow * lightIrradiance; - evalFragShading(diffuse, specular, normal, -getLightDirection(light), eyeDir, metallic, fresnel, roughness, albedo + evalFragShading(diffuse, specular, normal, -lightDir, eyeDir, metallic, fresnel, roughness, albedo <@if supportScattering@> ,scattering, midNormalCurvature, lowNormalCurvature <@endif@> diff --git a/libraries/render-utils/src/LightPoint.slh b/libraries/render-utils/src/LightPoint.slh index 767a96fb51..b120df584a 100644 --- a/libraries/render-utils/src/LightPoint.slh +++ b/libraries/render-utils/src/LightPoint.slh @@ -25,7 +25,7 @@ void evalLightingPoint(out vec3 diffuse, out vec3 specular, Light light, // Eval attenuation float radialAttenuation = evalLightAttenuation(light, fragLightDistance); - vec3 lightEnergy = radialAttenuation * shadow * getLightColor(light) * getLightIntensity(light); + vec3 lightEnergy = radialAttenuation * shadow * getLightIrradiance(light); // Eval shading evalFragShading(diffuse, specular, normal, fragLightDir, fragEyeDir, metallic, fresnel, roughness, albedo @@ -39,7 +39,7 @@ void evalLightingPoint(out vec3 diffuse, out vec3 specular, Light light, if (isShowLightContour() > 0.0) { // Show edge - float edge = abs(2.0 * ((getLightCutoffRadius(light) - fragLightDistance) / (0.1)) - 1.0); + float edge = abs(2.0 * ((lightVolume_getRadius(light.volume) - fragLightDistance) / (0.1)) - 1.0); if (edge < 1) { float edgeCoord = exp2(-8.0*edge*edge); diffuse = vec3(edgeCoord * edgeCoord * getLightColor(light)); diff --git a/libraries/render-utils/src/LightSpot.slh b/libraries/render-utils/src/LightSpot.slh index 65a417110a..3a04c28bfb 100644 --- a/libraries/render-utils/src/LightSpot.slh +++ b/libraries/render-utils/src/LightSpot.slh @@ -26,7 +26,7 @@ void evalLightingSpot(out vec3 diffuse, out vec3 specular, Light light, // Eval attenuation float radialAttenuation = evalLightAttenuation(light, fragLightDistance); float angularAttenuation = evalLightSpotAttenuation(light, cosSpotAngle); - vec3 lightEnergy = angularAttenuation * radialAttenuation * shadow * getLightColor(light) * getLightIntensity(light); + vec3 lightEnergy = angularAttenuation * radialAttenuation * shadow *getLightIrradiance(light); // Eval shading evalFragShading(diffuse, specular, normal, fragLightDir, fragEyeDir, metallic, fresnel, roughness, albedo @@ -40,8 +40,8 @@ void evalLightingSpot(out vec3 diffuse, out vec3 specular, Light light, if (isShowLightContour() > 0.0) { // Show edges - float edgeDistR = (getLightCutoffRadius(light) - fragLightDistance); - float edgeDistS = dot(fragLightDistance * vec2(cosSpotAngle, sqrt(1.0 - cosSpotAngle * cosSpotAngle)), -getLightSpotOutsideNormal2(light)); + float edgeDistR = (lightVolume_getRadius(light.volume) - fragLightDistance); + float edgeDistS = dot(fragLightDistance * vec2(cosSpotAngle, sqrt(1.0 - cosSpotAngle * cosSpotAngle)), -lightVolume_getSpotOutsideNormal2(light.volume)); float edgeDist = min(edgeDistR, edgeDistS); float edge = abs(2.0 * (edgeDist / (0.1)) - 1.0); if (edge < 1) { diff --git a/libraries/render-utils/src/deferred_light_point.slv b/libraries/render-utils/src/deferred_light_point.slv index 6bdc6fe42f..f126ee9251 100644 --- a/libraries/render-utils/src/deferred_light_point.slv +++ b/libraries/render-utils/src/deferred_light_point.slv @@ -34,7 +34,7 @@ void main(void) { Light light = getLight(instanceID); vec4 sphereVertex = inPosition; vec3 lightOrigin = getLightPosition(light); - vec4 sphereParam = getLightVolumeGeometry(light); + vec4 sphereParam = vec4(1.0); // = getLightVolumeGeometry(light); sphereVertex.xyz *= sphereParam.w; diff --git a/libraries/render-utils/src/deferred_light_spot.slv b/libraries/render-utils/src/deferred_light_spot.slv index c120fa28b1..5edd889704 100755 --- a/libraries/render-utils/src/deferred_light_spot.slv +++ b/libraries/render-utils/src/deferred_light_spot.slv @@ -31,7 +31,7 @@ void main(void) { int instanceID = lightIndex[gl_InstanceID]; Light light = getLight(instanceID); vec3 lightPos = getLightPosition(light); - vec4 coneParam = getLightVolumeGeometry(light); + vec4 coneParam = vec4(1.0); // = getLightVolumeGeometry(light); if(coneVertex.z >= 0.0) { // Evaluate the true position of the spot volume diff --git a/libraries/render-utils/src/local_lights_shading.slf b/libraries/render-utils/src/local_lights_shading.slf index eba65c39af..8cf817b127 100644 --- a/libraries/render-utils/src/local_lights_shading.slf +++ b/libraries/render-utils/src/local_lights_shading.slf @@ -94,7 +94,14 @@ void main(void) { vec4 fragEyeVector = invViewMat * vec4(-frag.position.xyz, 0.0); vec3 fragEyeDir = normalize(fragEyeVector.xyz); - // int numLights = lightIndex[0]; + + /* int theLightIndex = clusterGrid_getClusterLightId(0, cluster); + if (theLightIndex == 65535) { + discard; + } + Light light = getLight(theLightIndex); + + int numLights = lightIndex[0];*/ for (int i = 0; i < numLights; i++) { // Need the light now int theLightIndex = clusterGrid_getClusterLightId(i, cluster); @@ -105,11 +112,11 @@ void main(void) { vec4 fragLightDirLen; float cosSpotAngle; if (isSpot) { - if (!clipFragToLightVolumeSpot(light, fragPos.xyz, fragLightVecLen2, fragLightDirLen, cosSpotAngle)) { + if (!lightVolume_clipFragToLightVolumeSpot(light.volume, fragPos.xyz, fragLightVecLen2, fragLightDirLen, cosSpotAngle)) { continue; } } else { - if (!clipFragToLightVolumePoint(light, fragPos.xyz, fragLightVecLen2)) { + if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragPos.xyz, fragLightVecLen2)) { continue; } } diff --git a/libraries/render-utils/src/overlay3D.slf b/libraries/render-utils/src/overlay3D.slf index 1a629dedf1..0cb3340845 100644 --- a/libraries/render-utils/src/overlay3D.slf +++ b/libraries/render-utils/src/overlay3D.slf @@ -14,6 +14,7 @@ <@include model/Light.slh@> <$declareLightBuffer()$> +<$declareLightAmbientBuffer()$> <@include LightingModel.slh@> @@ -27,6 +28,11 @@ vec4 evalGlobalColor(float shadowAttenuation, vec3 position, vec3 normal, vec3 a // Need the light now Light light = getLight(); + vec3 lightDirection = getLightDirection(light); + vec3 lightIrradiance = getLightIrradiance(light); + + LightAmbient ambient = getLightAmbient(); + TransformCamera cam = getTransformCamera(); vec3 fragNormal; <$transformEyeToWorldDir(cam, normal, fragNormal)$> @@ -34,12 +40,12 @@ vec4 evalGlobalColor(float shadowAttenuation, vec3 position, vec3 normal, vec3 a vec3 fragEyeDir; <$transformEyeToWorldDir(cam, fragEyeVectorView, fragEyeDir)$> - vec3 color = opacity * albedo * getLightColor(light) * getLightAmbientIntensity(light); + vec3 color = opacity * albedo * getLightColor(light) * getLightAmbientIntensity(ambient); // Directional vec3 directionalDiffuse; vec3 directionalSpecular; - evalLightingDirectional(directionalDiffuse, directionalSpecular, light, fragEyeDir, fragNormal, roughness, metallic, fresnel, albedo, shadowAttenuation); + evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, fragEyeDir, fragNormal, roughness, metallic, fresnel, albedo, shadowAttenuation); color += directionalDiffuse * isDiffuseEnabled() * isDirectionalEnabled(); color += directionalSpecular * isSpecularEnabled() * isDirectionalEnabled(); diff --git a/libraries/render-utils/src/overlay3D_translucent.slf b/libraries/render-utils/src/overlay3D_translucent.slf index f45aa897f9..9bdac2d21f 100644 --- a/libraries/render-utils/src/overlay3D_translucent.slf +++ b/libraries/render-utils/src/overlay3D_translucent.slf @@ -14,6 +14,7 @@ <@include model/Light.slh@> <$declareLightBuffer()$> +<$declareLightAmbientBuffer()$> <@include LightingModel.slh@> @@ -27,6 +28,11 @@ vec4 evalGlobalColor(float shadowAttenuation, vec3 position, vec3 normal, vec3 a // Need the light now Light light = getLight(); + vec3 lightDirection = getLightDirection(light); + vec3 lightIrradiance = getLightIrradiance(light); + + LightAmbient ambient = getLightAmbient(); + TransformCamera cam = getTransformCamera(); vec3 fragNormal; <$transformEyeToWorldDir(cam, normal, fragNormal)$> @@ -34,12 +40,12 @@ vec4 evalGlobalColor(float shadowAttenuation, vec3 position, vec3 normal, vec3 a vec3 fragEyeDir; <$transformEyeToWorldDir(cam, fragEyeVectorView, fragEyeDir)$> - vec3 color = opacity * albedo * getLightColor(light) * getLightAmbientIntensity(light); + vec3 color = opacity * albedo * getLightColor(light) * getLightAmbientIntensity(ambient); // Directional vec3 directionalDiffuse; vec3 directionalSpecular; - evalLightingDirectional(directionalDiffuse, directionalSpecular, light, fragEyeDir, fragNormal, roughness, metallic, fresnel, albedo, shadowAttenuation); + evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, fragEyeDir, fragNormal, roughness, metallic, fresnel, albedo, shadowAttenuation); color += directionalDiffuse; color += directionalSpecular / opacity; diff --git a/libraries/render-utils/src/point_light.slf b/libraries/render-utils/src/point_light.slf index 239cbd5c91..e646db5069 100644 --- a/libraries/render-utils/src/point_light.slf +++ b/libraries/render-utils/src/point_light.slf @@ -58,7 +58,7 @@ void main(void) { // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space vec4 fragLightVecLen2; - if (!clipFragToLightVolumePoint(light, fragPos.xyz, fragLightVecLen2)) { + if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragPos.xyz, fragLightVecLen2)) { discard; } From bb5493106fbdba409645fbdf9a75fdbc242f79b8 Mon Sep 17 00:00:00 2001 From: samcake Date: Wed, 28 Sep 2016 18:33:34 -0700 Subject: [PATCH 42/75] smaller struct descriptions --- .../src/model/LightIrradiance.shared.slh | 39 ++++++++++ .../model/src/model/LightVolume.shared.slh | 75 +++++++++++++++++++ .../src/model/SphericalHarmonics.shared.slh | 57 ++++++++++++++ 3 files changed, 171 insertions(+) create mode 100644 libraries/model/src/model/LightIrradiance.shared.slh create mode 100644 libraries/model/src/model/LightVolume.shared.slh create mode 100644 libraries/model/src/model/SphericalHarmonics.shared.slh diff --git a/libraries/model/src/model/LightIrradiance.shared.slh b/libraries/model/src/model/LightIrradiance.shared.slh new file mode 100644 index 0000000000..5068f71480 --- /dev/null +++ b/libraries/model/src/model/LightIrradiance.shared.slh @@ -0,0 +1,39 @@ +// glsl / C++ compatible source as interface for Light +#ifndef LightIrradiance_Shared_slh +#define LightIrradiance_Shared_slh + +// +// Created by Sam Gateau on 14/9/2016. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + + +#define LightIrradianceConstRef LightIrradiance + +struct LightIrradiance { + vec3 color; + float intensity; + float falloffRadius; + float falloffSpot; + float spare1; + float spare2; +}; + + +vec3 lightIrradiance_getColor(LightIrradianceConstRef li) { return li.color; } +float lightIrradiance_getIntensity(LightIrradianceConstRef li) { return li.intensity; } +vec3 lightIrradiance_getIrradiance(LightIrradianceConstRef li) { return li.color * li.intensity; } +float lightIrradiance_getFalloffRadius(LightIrradianceConstRef li) { return li.falloffRadius; } +float lightIrradiance_getFalloffRadiusSquare(LightIrradianceConstRef li) { return li.falloffRadius * li.falloffRadius; } +float lightIrradiance_getFalloffSpot(LightIrradianceConstRef li) { return li.falloffSpot; } + + +#endif + + +// <@if 1@> +// Trigger Scribe include +// <@endif@> \ No newline at end of file diff --git a/libraries/model/src/model/LightVolume.shared.slh b/libraries/model/src/model/LightVolume.shared.slh new file mode 100644 index 0000000000..1ca32bd90e --- /dev/null +++ b/libraries/model/src/model/LightVolume.shared.slh @@ -0,0 +1,75 @@ +// glsl / C++ compatible source as interface for Light +#ifndef LightVolume_Shared_slh +#define LightVolume_Shared_slh + +// Light.shared.slh +// libraries/model/src/model +// +// Created by Sam Gateau on 14/9/2016. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + + +#define LightVolumeConstRef LightVolume + +struct LightVolume { + vec3 position; + float radius; + vec3 direction; + float spotCos; +}; + +bool lightVolume_isPoint(LightVolumeConstRef lv) { return bool(lv.spotCos < 0.f); } +bool lightVolume_isSpot(LightVolumeConstRef lv) { return bool(lv.spotCos >= 0.f); } + +vec3 lightVolume_getPosition(LightVolumeConstRef lv) { return lv.position; } +float lightVolume_getRadius(LightVolumeConstRef lv) { return lv.radius; } +float lightVolume_getRadiusSquare(LightVolumeConstRef lv) { return lv.radius * lv.radius; } +vec3 lightVolume_getDirection(LightVolumeConstRef lv) { return lv.direction; } // direction is -Z axis + +float lightVolume_getSpotAngleCos(LightVolumeConstRef lv) { return lv.spotCos; } +vec2 lightVolume_getSpotOutsideNormal2(LightVolumeConstRef lv) { return vec2(-sqrt(1.0 - lv.spotCos * lv.spotCos), lv.spotCos); } + + +bool lightVolume_clipFragToLightVolumePoint(LightVolume lv, vec3 fragPos, vec4 fragLightVecLen2) { + fragLightVecLen2 = vec4(lightVolume_getPosition(lv) - fragPos.xyz, 1.0f); + fragLightVecLen2.w = dot(fragLightVecLen2.xyz, fragLightVecLen2.xyz); + + // Kill if too far from the light center + if (fragLightVecLen2.w > lightVolume_getRadiusSquare(lv)) { + return false; + } + return true; +} + +bool lightVolume_clipFragToLightVolumeSpot(LightVolume lv, vec3 fragPos, vec4 fragLightVecLen2, vec4 fragLightDirLen, float cosSpotAngle) { + fragLightVecLen2 = vec4(lightVolume_getPosition(lv) - fragPos.xyz, 1.0f); + fragLightVecLen2.w = dot(fragLightVecLen2.xyz, fragLightVecLen2.xyz); + + // Kill if too far from the light center + if (fragLightVecLen2.w > lightVolume_getRadiusSquare(lv)) { + return false; + } + + // Allright we re valid in the volume + fragLightDirLen.w = length(fragLightVecLen2.xyz); + fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w; + + // Kill if not in the spot light (ah ah !) + cosSpotAngle = max(-dot(fragLightDirLen.xyz, lightVolume_getDirection(lv)), 0.0); + if (cosSpotAngle < lightVolume_getSpotAngleCos(lv)) { + return false; + } + + return true; +} + +#endif + + +// <@if 1@> +// Trigger Scribe include +// <@endif@> \ No newline at end of file diff --git a/libraries/model/src/model/SphericalHarmonics.shared.slh b/libraries/model/src/model/SphericalHarmonics.shared.slh new file mode 100644 index 0000000000..664c9e52db --- /dev/null +++ b/libraries/model/src/model/SphericalHarmonics.shared.slh @@ -0,0 +1,57 @@ +// glsl / C++ compatible source as interface for Light +#ifndef SphericalHarmonics_Shared_slh +#define SphericalHarmonics_Shared_slh + +// SphericalHarmonics.shared.slh +// libraries/model/src/model +// +// Created by Sam Gateau on 14/9/2016. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + + +#define SphericalHarmonicsConstRef SphericalHarmonics + +struct SphericalHarmonics { + vec4 L00; + vec4 L1m1; + vec4 L10; + vec4 L11; + vec4 L2m2; + vec4 L2m1; + vec4 L20; + vec4 L21; + vec4 L22; +}; + +vec4 sphericalHarmonics_evalSphericalLight(SphericalHarmonicsConstRef sh, vec3 direction) { + + vec3 dir = direction.xyz; + + const float C1 = 0.429043; + const float C2 = 0.511664; + const float C3 = 0.743125; + const float C4 = 0.886227; + const float C5 = 0.247708; + + vec4 value = C1 * sh.L22 * (dir.x * dir.x - dir.y * dir.y) + + C3 * sh.L20 * dir.z * dir.z + + C4 * sh.L00 - C5 * sh.L20 + + 2.0 * C1 * (sh.L2m2 * dir.x * dir.y + + sh.L21 * dir.x * dir.z + + sh.L2m1 * dir.y * dir.z) + + 2.0 * C2 * (sh.L11 * dir.x + + sh.L1m1 * dir.y + + sh.L10 * dir.z); + return value; +} + +#endif + + +// <@if 1@> +// Trigger Scribe include +// <@endif@> End C++ compatible \ No newline at end of file From 2a0e67ee2a84e4cae2df5d6c4c0ffa1a40e8d8f2 Mon Sep 17 00:00:00 2001 From: samcake Date: Thu, 29 Sep 2016 19:06:26 -0700 Subject: [PATCH 43/75] REvisiting the full lighting code to optimize the perf --- libraries/audio/src/AudioInjector.cpp | 2 +- libraries/model/src/model/Light.cpp | 67 ++++++----- libraries/model/src/model/Light.h | 107 +++++++++++------- libraries/model/src/model/Light.slh | 20 ---- .../src/model/LightIrradiance.shared.slh | 42 +++++-- .../model/src/model/LightVolume.shared.slh | 46 ++++---- .../src/DeferredLightingEffect.cpp | 4 +- .../render-utils/src/LightClusterGrid.slh | 6 +- libraries/render-utils/src/LightClusters.cpp | 4 +- libraries/render-utils/src/LightClusters.h | 2 +- libraries/render-utils/src/LightPoint.slh | 2 +- libraries/render-utils/src/LightSpot.slh | 5 +- libraries/render-utils/src/LightStage.cpp | 8 +- .../render-utils/src/SubsurfaceScattering.cpp | 2 +- .../render-utils/src/local_lights_shading.slf | 37 +++--- 15 files changed, 186 insertions(+), 168 deletions(-) diff --git a/libraries/audio/src/AudioInjector.cpp b/libraries/audio/src/AudioInjector.cpp index 43701a51d8..95cb3c9fb3 100644 --- a/libraries/audio/src/AudioInjector.cpp +++ b/libraries/audio/src/AudioInjector.cpp @@ -26,7 +26,7 @@ #include "SoundCache.h" #include "AudioSRC.h" -int audioInjectorPtrMetaTypeId = qRegisterMetaType(); +//int audioInjectorPtrMetaTypeId = qRegisterMetaType(); AbstractAudioInterface* AudioInjector::_localAudioInterface{ nullptr }; diff --git a/libraries/model/src/model/Light.cpp b/libraries/model/src/model/Light.cpp index c073e397dd..449054c9b2 100755 --- a/libraries/model/src/model/Light.cpp +++ b/libraries/model/src/model/Light.cpp @@ -13,22 +13,19 @@ using namespace model; Light::Light() { - // only if created from nothing shall we create the Buffer to store the properties - Schema schema; - _schemaBuffer = std::make_shared(sizeof(Schema), (const gpu::Byte*) &schema); updateLightRadius(); } Light::Light(const Light& light) : _flags(light._flags), - _schemaBuffer(light._schemaBuffer), _transform(light._transform) { } Light& Light::operator= (const Light& light) { _flags = (light._flags); - _schemaBuffer = (light._schemaBuffer); + _lightSchemaBuffer = (light._lightSchemaBuffer); + _ambientSchemaBuffer = (light._ambientSchemaBuffer); _transform = (light._transform); return (*this); @@ -38,15 +35,22 @@ Light::~Light() { } void Light::setType(Type type) { - editSchema()._control.x = float(type); - updateLightRadius(); + if (_type != type) { + _type = type; + if (type != SPOT) { + _lightSchemaBuffer.edit().volume.spotCos = -1.f; + } else { + _lightSchemaBuffer.edit().volume.spotCos = _spotCos; + } + updateLightRadius(); + } updateVolumeGeometry(); } void Light::setPosition(const Vec3& position) { _transform.setTranslation(position); - editSchema()._position = Vec4(position, 1.f); + _lightSchemaBuffer.edit().volume.position = position; } void Light::setOrientation(const glm::quat& orientation) { @@ -55,39 +59,35 @@ void Light::setOrientation(const glm::quat& orientation) { } void Light::setDirection(const Vec3& direction) { - editSchema()._direction = glm::normalize(direction); + _lightSchemaBuffer.edit().volume.direction = (direction); } const Vec3& Light::getDirection() const { - return getSchema()._direction; + return _lightSchemaBuffer->volume.direction; } void Light::setColor(const Color& color) { - editSchema()._color = color; + _lightSchemaBuffer.edit().irradiance.color = color; updateLightRadius(); } void Light::setIntensity(float intensity) { - editSchema()._intensity = intensity; + _lightSchemaBuffer.edit().irradiance.intensity = intensity; updateLightRadius(); } -void Light::setAmbientIntensity(float intensity) { - editSchema()._ambientIntensity = intensity; -} - void Light::setFalloffRadius(float radius) { if (radius <= 0.0f) { radius = 0.1f; } - editSchema()._attenuation.x = radius; + _lightSchemaBuffer.edit().irradiance.falloffRadius = radius; updateLightRadius(); } void Light::setMaximumRadius(float radius) { if (radius <= 0.f) { radius = 1.0f; } - editSchema()._attenuation.y = radius; + _lightSchemaBuffer.edit().volume.radius = radius; updateLightRadius(); updateVolumeGeometry(); } @@ -106,7 +106,7 @@ void Light::updateLightRadius() { float cutoffRadius = getFalloffRadius() * ((glm::sqrt(intensity / MIN_CUTOFF_INTENSITY) - 1) - 1); // If it is less than max radius, store it to buffer to avoid extra shading - editSchema()._attenuation.z = std::min(getMaximumRadius(), cutoffRadius); + _lightSchemaBuffer.edit().irradiance.cutoffRadius = std::min(getMaximumRadius(), cutoffRadius); } #include @@ -119,12 +119,13 @@ void Light::setSpotAngle(float angle) { if (dangle > glm::half_pi()) { dangle = glm::half_pi(); } - auto cosAngle = cos(dangle); auto sinAngle = sin(dangle); - editSchema()._spot.x = (float) std::abs(cosAngle); - editSchema()._spot.y = (float) std::abs(sinAngle); - editSchema()._spot.z = (float) angle; + _spotCos = (float)std::abs(cosAngle); + + if (isSpot()) { + _lightSchemaBuffer.edit().volume.spotCos = _spotCos; + } updateVolumeGeometry(); } @@ -133,22 +134,20 @@ void Light::setSpotExponent(float exponent) { if (exponent <= 0.f) { exponent = 0.0f; } - editSchema()._spot.w = exponent; + _lightSchemaBuffer.edit().irradiance.falloffSpot = exponent; } -void Light::setShowContour(float show) { - if (show <= 0.f) { - show = 0.0f; - } - editSchema()._control.z = show; + +void Light::setAmbientIntensity(float intensity) { + _ambientSchemaBuffer.edit().intensity = intensity; } void Light::setAmbientSphere(const gpu::SphericalHarmonics& sphere) { - editSchema()._ambientSphere = sphere; + _ambientSchemaBuffer.edit().ambientSphere = sphere; } void Light::setAmbientSpherePreset(gpu::SphericalHarmonics::Preset preset) { - editSchema()._ambientSphere.assignPreset(preset); + _ambientSchemaBuffer.edit().ambientSphere.assignPreset(preset); } void Light::setAmbientMap(gpu::TexturePointer ambientMap) { @@ -161,17 +160,17 @@ void Light::setAmbientMap(gpu::TexturePointer ambientMap) { } void Light::setAmbientMapNumMips(uint16_t numMips) { - editSchema()._ambientMapNumMips = (float)numMips; + _ambientSchemaBuffer.edit().mapNumMips = (float)numMips; } void Light::updateVolumeGeometry() { // enlarge the scales slightly to account for tesselation - const float SCALE_EXPANSION = 0.05f; + /* const float SCALE_EXPANSION = 0.05f; glm::vec4 volumeGeometry(0.0f, 0.0f, 0.0f, getMaximumRadius() * (1.0f + SCALE_EXPANSION)); if (getType() == SPOT) { const float TANGENT_LENGTH_SCALE = 0.666f; volumeGeometry = glm::vec4(getSpotAngleCosSin(), TANGENT_LENGTH_SCALE * tanf(0.5f * getSpotAngle()), volumeGeometry.w); } - editSchema()._volumeGeometry = volumeGeometry; + editSchema()._volumeGeometry = volumeGeometry;*/ } diff --git a/libraries/model/src/model/Light.h b/libraries/model/src/model/Light.h index f1c68bb93a..893467866a 100755 --- a/libraries/model/src/model/Light.h +++ b/libraries/model/src/model/Light.h @@ -31,37 +31,38 @@ class Light { public: struct LightVolume { - vec3 position; - float radius; - vec3 direction; - float spotCos; + vec3 position { 0.f }; + float radius { 1.0f }; + vec3 direction { 0.f, 0.f, -1.f }; + float spotCos { -1.f }; - bool isPoint() { return bool(spotCos < 0.f); } - bool isSpot() { return bool(spotCos >= 0.f); } + bool isPoint() const { return bool(spotCos < 0.f); } + bool isSpot() const { return bool(spotCos >= 0.f); } - vec3 getPosition() { return position; } - float getRadius() { return radius; } - float getRadiusSquare() { return radius * radius; } - vec3 getDirection() { return direction; } + vec3 getPosition() const { return position; } + float getRadius() const { return radius; } + float getRadiusSquare() const { return radius * radius; } + vec3 getDirection() const { return direction; } - float getSpotAngleCos() { return spotCos; } + float getSpotAngleCos() const { return spotCos; } + vec2 getSpotAngleCosSin() const { return vec2(spotCos, sqrt(1.f - spotCos * spotCos)); } }; struct LightIrradiance { - vec3 color; - float intensity; - float falloffRadius; - float falloffSpot; + vec3 color { 1.f }; + float intensity { 1.f }; + float falloffRadius { 0.1f }; + float cutoffRadius { 0.1f }; + float falloffSpot { 1.f }; float spare1; - float spare2; - vec3 getColor() { return color; } - float getIntensity() { return intensity; } - vec3 getIrradiance() { return color * intensity; } - float getFalloffRadius() { return falloffRadius; } - float getFalloffRadiusSquare() { return falloffRadius * falloffRadius; } - float getFalloffSpot() { return falloffSpot; } + vec3 getColor() const { return color; } + float getIntensity() const { return intensity; } + vec3 getIrradiance() const { return color * intensity; } + float getFalloffRadius() const { return falloffRadius; } + float getCutoffRadius() const { return cutoffRadius; } + float getFalloffSpot() const { return falloffSpot; } }; @@ -93,7 +94,7 @@ public: virtual ~Light(); void setType(Type type); - Type getType() const { return Type((int) getSchema()._control.x); } + Type getType() const { return _type; } void setPosition(const Vec3& position); const Vec3& getPosition() const { return _transform.getTranslation(); } @@ -104,10 +105,10 @@ public: void setOrientation(const Quat& orientation); const glm::quat& getOrientation() const { return _transform.getRotation(); } - const Color& getColor() const { return getSchema()._color; } + const Color& getColor() const { return _lightSchemaBuffer->irradiance.color; } void setColor(const Color& color); - float getIntensity() const { return getSchema()._intensity; } + float getIntensity() const { return _lightSchemaBuffer->irradiance.intensity; } void setIntensity(float intensity); bool isRanged() const { return (getType() == POINT) || (getType() == SPOT ); } @@ -116,44 +117,58 @@ public: // expressed in meters. It is used only to calculate the falloff curve of the light. // Actual rendered lights will all have surface radii approaching 0. void setFalloffRadius(float radius); - float getFalloffRadius() const { return getSchema()._attenuation.x; } + float getFalloffRadius() const { return _lightSchemaBuffer->irradiance.falloffRadius; } // Maximum radius is the cutoff radius of the light energy, expressed in meters. // It is used to bound light entities, and *will not* affect the falloff curve of the light. // Setting it low will result in a noticeable cutoff. void setMaximumRadius(float radius); - float getMaximumRadius() const { return getSchema()._attenuation.y; } + float getMaximumRadius() const { return _lightSchemaBuffer->volume.radius; } // Spot properties bool isSpot() const { return getType() == SPOT; } void setSpotAngle(float angle); - float getSpotAngle() const { return getSchema()._spot.z; } - glm::vec2 getSpotAngleCosSin() const { return glm::vec2(getSchema()._spot.x, getSchema()._spot.y); } + float getSpotAngle() const { return acos(_lightSchemaBuffer->volume.getSpotAngleCos()); } + glm::vec2 getSpotAngleCosSin() const { return _lightSchemaBuffer->volume.getSpotAngleCosSin(); } void setSpotExponent(float exponent); - float getSpotExponent() const { return getSchema()._spot.w; } - - // For editing purpose, show the light volume contour. - // Set to non 0 to show it, the value is used as the intensity of the contour color - void setShowContour(float show); - float getShowContour() const { return getSchema()._control.z; } + float getSpotExponent() const { return _lightSchemaBuffer->irradiance.falloffSpot; } // If the light has an ambient (Indirect) component, then the Ambientintensity can be used to control its contribution to the lighting void setAmbientIntensity(float intensity); - float getAmbientIntensity() const { return getSchema()._ambientIntensity; } + float getAmbientIntensity() const { return _ambientSchemaBuffer->intensity; } // Spherical Harmonics storing the Ambient lighting approximation used for the Sun typed light void setAmbientSphere(const gpu::SphericalHarmonics& sphere); - const gpu::SphericalHarmonics& getAmbientSphere() const { return getSchema()._ambientSphere; } + const gpu::SphericalHarmonics& getAmbientSphere() const { return _ambientSchemaBuffer->ambientSphere; } void setAmbientSpherePreset(gpu::SphericalHarmonics::Preset preset); void setAmbientMap(gpu::TexturePointer ambientMap); gpu::TexturePointer getAmbientMap() const { return _ambientMap; } void setAmbientMapNumMips(uint16_t numMips); - uint16_t getAmbientMapNumMips() const { return (uint16_t) getSchema()._ambientMapNumMips; } + uint16_t getAmbientMapNumMips() const { return (uint16_t) _ambientSchemaBuffer->mapNumMips; } + + // LIght Schema + class LightSchema { + public: + LightVolume volume; + LightIrradiance irradiance; + }; + + class AmbientSchema { + public: + float intensity { 0.f }; + float mapNumMips { 0.f }; + float spare1; + float spare2; + gpu::SphericalHarmonics ambientSphere; + }; + + using LightSchemaBuffer = gpu::StructBuffer; + using AmbientSchemaBuffer = gpu::StructBuffer; // Schema to access the attribute values of the light - class Schema { + /* class Schema { public: Vec4 _position{0.0f, 0.0f, 0.0f, 1.0f}; Vec3 _direction{0.0f, 0.0f, -1.0f}; @@ -172,19 +187,23 @@ public: gpu::SphericalHarmonics _ambientSphere; }; - - const UniformBufferView& getSchemaBuffer() const { return _schemaBuffer; } + */ + const LightSchemaBuffer& getLightSchemaBuffer() const { return _lightSchemaBuffer; } + const AmbientSchemaBuffer& getAmbientSchemaBuffer() const { return _ambientSchemaBuffer; } protected: Flags _flags{ 0 }; - UniformBufferView _schemaBuffer; + + LightSchemaBuffer _lightSchemaBuffer; + AmbientSchemaBuffer _ambientSchemaBuffer; + Transform _transform; gpu::TexturePointer _ambientMap; - const Schema& getSchema() const { return _schemaBuffer.get(); } - Schema& editSchema() { return _schemaBuffer.edit(); } + Type _type { SUN }; + float _spotCos { -1.0f }; // stored here to be able to reset the spot angle when turning the type spot on/off void updateLightRadius(); void updateVolumeGeometry(); diff --git a/libraries/model/src/model/Light.slh b/libraries/model/src/model/Light.slh index 6e9f92e67f..78fa11416d 100644 --- a/libraries/model/src/model/Light.slh +++ b/libraries/model/src/model/Light.slh @@ -23,26 +23,6 @@ struct Light { LightIrradiance irradiance; }; -// Light is the light source its self, d is the light's distance calculated as length(unnormalized light vector). -float evalLightAttenuation(Light l, float d) { - float radius = lightIrradiance_getFalloffRadius(l.irradiance); - float cutoff = lightVolume_getRadius(l.volume); - float denom = d / radius + 1.0; - float attenuation = 1.0 / (denom * denom); - - - // "Fade" the edges of light sources to make things look a bit more attractive. - // Note: this tends to look a bit odd at lower exponents. - attenuation *= min(1, max(0, -(d - cutoff))); - - return attenuation; -} - - -float evalLightSpotAttenuation(Light l, float cosA) { - return pow(cosA, lightIrradiance_getFalloffSpot(l.irradiance)); -} - bool light_isSpot(Light l) { return lightVolume_isSpot(l.volume); } vec3 getLightPosition(Light l) { return lightVolume_getPosition(l.volume); } diff --git a/libraries/model/src/model/LightIrradiance.shared.slh b/libraries/model/src/model/LightIrradiance.shared.slh index 5068f71480..eaa1b33a88 100644 --- a/libraries/model/src/model/LightIrradiance.shared.slh +++ b/libraries/model/src/model/LightIrradiance.shared.slh @@ -14,21 +14,39 @@ #define LightIrradianceConstRef LightIrradiance struct LightIrradiance { - vec3 color; - float intensity; - float falloffRadius; - float falloffSpot; - float spare1; - float spare2; + vec4 colorIntensity; + // falloffRadius, cutoffRadius, falloffSpot, spare + vec4 attenuation; }; -vec3 lightIrradiance_getColor(LightIrradianceConstRef li) { return li.color; } -float lightIrradiance_getIntensity(LightIrradianceConstRef li) { return li.intensity; } -vec3 lightIrradiance_getIrradiance(LightIrradianceConstRef li) { return li.color * li.intensity; } -float lightIrradiance_getFalloffRadius(LightIrradianceConstRef li) { return li.falloffRadius; } -float lightIrradiance_getFalloffRadiusSquare(LightIrradianceConstRef li) { return li.falloffRadius * li.falloffRadius; } -float lightIrradiance_getFalloffSpot(LightIrradianceConstRef li) { return li.falloffSpot; } +vec3 lightIrradiance_getColor(LightIrradiance li) { return li.colorIntensity.xyz; } +float lightIrradiance_getIntensity(LightIrradiance li) { return li.colorIntensity.w; } +vec3 lightIrradiance_getIrradiance(LightIrradiance li) { return li.colorIntensity.xyz * li.colorIntensity.w; } +float lightIrradiance_getFalloffRadius(LightIrradiance li) { return li.attenuation.x; } +float lightIrradiance_getCutoffRadius(LightIrradiance li) { return li.attenuation.y; } +float lightIrradiance_getFalloffSpot(LightIrradiance li) { return li.attenuation.z; } + + +// Light is the light source its self, d is the light's distance calculated as length(unnormalized light vector). +float lightIrradiance_evalLightAttenuation(LightIrradiance li, float d) { + float radius = lightIrradiance_getFalloffRadius(li); + float cutoff = lightIrradiance_getCutoffRadius(li); + float denom = d / radius + 1.0; + float attenuation = 1.0 / (denom * denom); + + + // "Fade" the edges of light sources to make things look a bit more attractive. + // Note: this tends to look a bit odd at lower exponents. + attenuation *= min(1, max(0, -(d - cutoff))); + + return attenuation; +} + + +float lightIrradiance_evalLightSpotAttenuation(LightIrradiance li, float cosA) { + return pow(cosA, lightIrradiance_getFalloffSpot(li)); +} #endif diff --git a/libraries/model/src/model/LightVolume.shared.slh b/libraries/model/src/model/LightVolume.shared.slh index 1ca32bd90e..ac75308c18 100644 --- a/libraries/model/src/model/LightVolume.shared.slh +++ b/libraries/model/src/model/LightVolume.shared.slh @@ -16,37 +16,33 @@ #define LightVolumeConstRef LightVolume struct LightVolume { - vec3 position; - float radius; - vec3 direction; - float spotCos; + vec4 positionRadius; + vec4 directionSpotCos; }; -bool lightVolume_isPoint(LightVolumeConstRef lv) { return bool(lv.spotCos < 0.f); } -bool lightVolume_isSpot(LightVolumeConstRef lv) { return bool(lv.spotCos >= 0.f); } +bool lightVolume_isPoint(LightVolume lv) { return bool(lv.directionSpotCos.w < 0.f); } +bool lightVolume_isSpot(LightVolume lv) { return bool(lv.directionSpotCos.w >= 0.f); } -vec3 lightVolume_getPosition(LightVolumeConstRef lv) { return lv.position; } -float lightVolume_getRadius(LightVolumeConstRef lv) { return lv.radius; } -float lightVolume_getRadiusSquare(LightVolumeConstRef lv) { return lv.radius * lv.radius; } -vec3 lightVolume_getDirection(LightVolumeConstRef lv) { return lv.direction; } // direction is -Z axis +vec3 lightVolume_getPosition(LightVolume lv) { return lv.positionRadius.xyz; } +float lightVolume_getRadius(LightVolume lv) { return lv.positionRadius.w; } +float lightVolume_getRadiusSquare(LightVolume lv) { return lv.positionRadius.w * lv.positionRadius.w; } +vec3 lightVolume_getDirection(LightVolume lv) { return lv.directionSpotCos.xyz; } // direction is -Z axis -float lightVolume_getSpotAngleCos(LightVolumeConstRef lv) { return lv.spotCos; } -vec2 lightVolume_getSpotOutsideNormal2(LightVolumeConstRef lv) { return vec2(-sqrt(1.0 - lv.spotCos * lv.spotCos), lv.spotCos); } +float lightVolume_getSpotAngleCos(LightVolume lv) { return lv.directionSpotCos.w; } +vec2 lightVolume_getSpotOutsideNormal2(LightVolume lv) { return vec2(-sqrt(1.0 - lv.directionSpotCos.w * lv.directionSpotCos.w), lv.directionSpotCos.w); } -bool lightVolume_clipFragToLightVolumePoint(LightVolume lv, vec3 fragPos, vec4 fragLightVecLen2) { - fragLightVecLen2 = vec4(lightVolume_getPosition(lv) - fragPos.xyz, 1.0f); +bool lightVolume_clipFragToLightVolumePoint(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2) { + fragLightVecLen2.xyz = lightVolume_getPosition(lv) - fragPos.xyz; fragLightVecLen2.w = dot(fragLightVecLen2.xyz, fragLightVecLen2.xyz); // Kill if too far from the light center - if (fragLightVecLen2.w > lightVolume_getRadiusSquare(lv)) { - return false; - } - return true; + return (fragLightVecLen2.w <= lightVolume_getRadiusSquare(lv)); } -bool lightVolume_clipFragToLightVolumeSpot(LightVolume lv, vec3 fragPos, vec4 fragLightVecLen2, vec4 fragLightDirLen, float cosSpotAngle) { - fragLightVecLen2 = vec4(lightVolume_getPosition(lv) - fragPos.xyz, 1.0f); + +bool lightVolume_clipFragToLightVolumeSpot(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2, out vec4 fragLightDirLen, out float cosSpotAngle) { + fragLightVecLen2.xyz = lightVolume_getPosition(lv) - fragPos.xyz; fragLightVecLen2.w = dot(fragLightVecLen2.xyz, fragLightVecLen2.xyz); // Kill if too far from the light center @@ -67,6 +63,16 @@ bool lightVolume_clipFragToLightVolumeSpot(LightVolume lv, vec3 fragPos, vec4 fr return true; } +bool lightVolume_clipFragToLightVolumeSpotSide(LightVolume lv, vec4 fragLightVecLen2, out vec4 fragLightDirLen, out float cosSpotAngle) { + // Allright we re valid in the volume + fragLightDirLen.w = length(fragLightVecLen2.xyz); + fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w; + + // Kill if not in the spot light (ah ah !) + cosSpotAngle = max(-dot(fragLightDirLen.xyz, lightVolume_getDirection(lv)), 0.0); + return (cosSpotAngle >= lightVolume_getSpotAngleCos(lv)); +} + #endif diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index 59a75a5389..01c5a81732 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -187,7 +187,7 @@ void DeferredLightingEffect::setupKeyLightBatch(gpu::Batch& batch, int lightBuff auto keyLight = _allocatedLights[_globalLights.front()]; if (lightBufferUnit >= 0) { - batch.setUniformBuffer(lightBufferUnit, keyLight->getSchemaBuffer()); + batch.setUniformBuffer(lightBufferUnit, keyLight->getLightSchemaBuffer()); } if (keyLight->getAmbientMap() && (skyboxCubemapUnit >= 0)) { @@ -727,8 +727,6 @@ void RenderDeferredLocals::run(const render::SceneContextPointer& sceneContext, // Bind the global list of lights and the visible lights this frame batch.setUniformBuffer(deferredLightingEffect->_localLightLocations->lightBufferUnit, lightClusters->_lightStage->_lightArrayBuffer); - batch.setUniformBuffer(deferredLightingEffect->_localLightLocations->lightIndexBufferUnit, lightClusters->_lightIndicesBuffer); - batch.setUniformBuffer(LIGHT_CLUSTER_GRID_FRUSTUM_GRID_SLOT, lightClusters->_frustumGridBuffer); batch.setUniformBuffer(LIGHT_CLUSTER_GRID_CLUSTER_GRID_SLOT, lightClusters->_clusterGridBuffer); diff --git a/libraries/render-utils/src/LightClusterGrid.slh b/libraries/render-utils/src/LightClusterGrid.slh index 7964d09142..3395f1be1a 100644 --- a/libraries/render-utils/src/LightClusterGrid.slh +++ b/libraries/render-utils/src/LightClusterGrid.slh @@ -64,9 +64,11 @@ ivec2 clusterGrid_getCluster(int index) { int clusterGrid_getClusterLightId(int index, ivec2 cluster) { int arrayElement = cluster.y + index; - int element = _clusterGridContent[arrayElement >> 1]; + int element = _clusterGridContent[arrayElement]; + return element; +// int element = _clusterGridContent[arrayElement >> 1]; - return (((arrayElement & 0x00000001) == 1) ? (element >> 16) : element) & 0x0000FFFF; +// return (((arrayElement & 0x00000001) == 1) ? (element >> 16) : element) & 0x0000FFFF; } <@endif@> diff --git a/libraries/render-utils/src/LightClusters.cpp b/libraries/render-utils/src/LightClusters.cpp index 651ba4957d..cf79e30630 100644 --- a/libraries/render-utils/src/LightClusters.cpp +++ b/libraries/render-utils/src/LightClusters.cpp @@ -76,7 +76,7 @@ const glm::uvec4 LightClusters::MAX_GRID_DIMENSIONS { 32, 32, 31, 16384 }; LightClusters::LightClusters() : _lightIndicesBuffer(std::make_shared()), _clusterGridBuffer(std::make_shared(), gpu::Element::INDEX_INT32), - _clusterContentBuffer(std::make_shared(), gpu::Element::INDEX_UINT16) { + _clusterContentBuffer(std::make_shared(), gpu::Element::INDEX_INT32) { auto dims = _frustumGridBuffer.edit().dims; _frustumGridBuffer.edit().dims = ivec3(0); // make sure we go through the full reset of the dimensionts ion the setDImensions call setDimensions(dims, MAX_GRID_DIMENSIONS.w); @@ -109,7 +109,7 @@ void LightClusters::setDimensions(glm::uvec3 gridDims, uint32_t listBudget) { _clusterGridBuffer._size = _clusterGridBuffer._buffer->resize(_numClusters * sizeof(uint32_t)); } - auto configListBudget = std::min(MAX_GRID_DIMENSIONS.w, listBudget) * 2; + auto configListBudget = std::min(MAX_GRID_DIMENSIONS.w, listBudget); if (configListBudget != _clusterContentBuffer.getNumElements()) { _clusterContent.clear(); _clusterContent.resize(configListBudget, INVALID_LIGHT); diff --git a/libraries/render-utils/src/LightClusters.h b/libraries/render-utils/src/LightClusters.h index 02ea436718..7b50d8864a 100644 --- a/libraries/render-utils/src/LightClusters.h +++ b/libraries/render-utils/src/LightClusters.h @@ -94,7 +94,7 @@ public: const uint32_t EMPTY_CLUSTER { 0x0000FFFF }; const LightID INVALID_LIGHT { LightStage::INVALID_INDEX }; - using LightIndex = uint16_t; + using LightIndex = uint32_t; std::vector _clusterGrid; std::vector _clusterContent; diff --git a/libraries/render-utils/src/LightPoint.slh b/libraries/render-utils/src/LightPoint.slh index b120df584a..362aac5298 100644 --- a/libraries/render-utils/src/LightPoint.slh +++ b/libraries/render-utils/src/LightPoint.slh @@ -24,7 +24,7 @@ void evalLightingPoint(out vec3 diffuse, out vec3 specular, Light light, vec3 fragLightDir = fragLightVec / fragLightDistance; // Eval attenuation - float radialAttenuation = evalLightAttenuation(light, fragLightDistance); + float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance); vec3 lightEnergy = radialAttenuation * shadow * getLightIrradiance(light); // Eval shading diff --git a/libraries/render-utils/src/LightSpot.slh b/libraries/render-utils/src/LightSpot.slh index 3a04c28bfb..a3be944494 100644 --- a/libraries/render-utils/src/LightSpot.slh +++ b/libraries/render-utils/src/LightSpot.slh @@ -23,9 +23,10 @@ void evalLightingSpot(out vec3 diffuse, out vec3 specular, Light light, float fragLightDistance = fragLightDirLen.w; vec3 fragLightDir = fragLightDirLen.xyz; + // Eval attenuation - float radialAttenuation = evalLightAttenuation(light, fragLightDistance); - float angularAttenuation = evalLightSpotAttenuation(light, cosSpotAngle); + float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance); + float angularAttenuation = lightIrradiance_evalLightSpotAttenuation(light.irradiance, cosSpotAngle); vec3 lightEnergy = angularAttenuation * radialAttenuation * shadow *getLightIrradiance(light); // Eval shading diff --git a/libraries/render-utils/src/LightStage.cpp b/libraries/render-utils/src/LightStage.cpp index 357e7f46f7..bedd22b360 100644 --- a/libraries/render-utils/src/LightStage.cpp +++ b/libraries/render-utils/src/LightStage.cpp @@ -134,22 +134,22 @@ LightStage::LightPointer LightStage::removeLight(Index index) { } void LightStage::updateLightArrayBuffer(Index lightId) { + auto lightSize = sizeof(model::Light::LightSchema); if (!_lightArrayBuffer) { _lightArrayBuffer = std::make_shared(); } assert(checkLightId(lightId)); - auto lightSize = sizeof(model::Light::Schema); - if (lightId > (Index) _lightArrayBuffer->getNumTypedElements()) { + if (lightId > (Index)_lightArrayBuffer->getNumTypedElements()) { _lightArrayBuffer->resize(lightSize * (lightId + 10)); } // lightArray is big enough so we can remap auto light = _lights._elements[lightId]; if (light) { - auto lightSchema = light->getSchemaBuffer().get(); - _lightArrayBuffer->setSubData(lightId, lightSchema); + const auto& lightSchema = light->getLightSchemaBuffer().get(); + _lightArrayBuffer->setSubData(lightId, lightSchema); } else { // this should not happen ? } diff --git a/libraries/render-utils/src/SubsurfaceScattering.cpp b/libraries/render-utils/src/SubsurfaceScattering.cpp index 7cfb717f12..1fea7d6ced 100644 --- a/libraries/render-utils/src/SubsurfaceScattering.cpp +++ b/libraries/render-utils/src/SubsurfaceScattering.cpp @@ -568,7 +568,7 @@ void DebugSubsurfaceScattering::run(const render::SceneContextPointer& sceneCont batch.setUniformBuffer(ScatteringTask_FrameTransformSlot, frameTransform->getFrameTransformBuffer()); batch.setUniformBuffer(ScatteringTask_ParamSlot, scatteringResource->getParametersBuffer()); if (light) { - batch.setUniformBuffer(ScatteringTask_LightSlot, light->getSchemaBuffer()); + batch.setUniformBuffer(ScatteringTask_LightSlot, light->getLightSchemaBuffer()); } batch.setResourceTexture(ScatteringTask_ScatteringTableSlot, scatteringTable); batch.setResourceTexture(ScatteringTask_CurvatureMapSlot, curvatureFramebuffer->getRenderBuffer(0)); diff --git a/libraries/render-utils/src/local_lights_shading.slf b/libraries/render-utils/src/local_lights_shading.slf index 8cf817b127..3d85c0ccab 100644 --- a/libraries/render-utils/src/local_lights_shading.slf +++ b/libraries/render-utils/src/local_lights_shading.slf @@ -20,9 +20,6 @@ // Everything about light <@include model/Light.slh@> <$declareLightBuffer(128)$> -uniform lightIndexBuffer { - int lightIndex[128]; -}; <@include LightingModel.slh@> @@ -94,33 +91,31 @@ void main(void) { vec4 fragEyeVector = invViewMat * vec4(-frag.position.xyz, 0.0); vec3 fragEyeDir = normalize(fragEyeVector.xyz); - - /* int theLightIndex = clusterGrid_getClusterLightId(0, cluster); - if (theLightIndex == 65535) { - discard; - } - Light light = getLight(theLightIndex); - - int numLights = lightIndex[0];*/ - for (int i = 0; i < numLights; i++) { + int numLightTouching = 0; + for (int i = 0; i < numLights && numLightTouching < 16; i++) { // Need the light now int theLightIndex = clusterGrid_getClusterLightId(i, cluster); Light light = getLight(theLightIndex); + bool isSpot = light_isSpot(light); // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space vec4 fragLightVecLen2; vec4 fragLightDirLen; float cosSpotAngle; - if (isSpot) { - if (!lightVolume_clipFragToLightVolumeSpot(light.volume, fragPos.xyz, fragLightVecLen2, fragLightDirLen, cosSpotAngle)) { + if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragPos.xyz, fragLightVecLen2)) { + continue; + } + if (isSpot && !lightVolume_clipFragToLightVolumeSpotSide(light.volume, fragLightVecLen2, fragLightDirLen, cosSpotAngle)) { continue; - } - } else { - if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragPos.xyz, fragLightVecLen2)) { - continue; - } } + if (dot(frag.normal, normalize(fragLightVecLen2.xyz)) < 0.0) { + //_fragColor.rgb += vec3(0.0, 0.0, 1.0 / 16.0); + continue; + } + + numLightTouching++; + /* vec3 diffuse; vec3 specular; @@ -135,11 +130,11 @@ void main(void) { frag.metallic, frag.fresnel, frag.albedo, 1.0, frag.scattering, midNormalCurvature, lowNormalCurvature); } - _fragColor.rgb += diffuse; _fragColor.rgb += specular; + */ + _fragColor.rgb += vec3(1.0/16.0, 0.0, 0.0); } - // _fragColor.rgb += vec3(0.05, 0.0, 0.0); } From e143c05ef83e9e798129a5afa38df31d9e4d28c7 Mon Sep 17 00:00:00 2001 From: sam Date: Fri, 30 Sep 2016 02:41:21 -0700 Subject: [PATCH 44/75] Keep on investigating the shading cost per light --- .../model/src/model/LightVolume.shared.slh | 41 ++---- .../render-utils/src/LightClusterGrid.slh | 7 +- libraries/render-utils/src/LightClusters.cpp | 29 +++-- libraries/render-utils/src/LightPoint.slh | 8 +- libraries/render-utils/src/LightingModel.slh | 39 +++++- .../src/lightClusters_drawClusterContent.slv | 4 +- .../lightClusters_drawClusterFromDepth.slf | 4 +- .../src/lightClusters_drawGrid.slv | 4 +- .../render-utils/src/local_lights_shading.slf | 121 ++++++++++++++---- 9 files changed, 173 insertions(+), 84 deletions(-) diff --git a/libraries/model/src/model/LightVolume.shared.slh b/libraries/model/src/model/LightVolume.shared.slh index ac75308c18..a78667ed6c 100644 --- a/libraries/model/src/model/LightVolume.shared.slh +++ b/libraries/model/src/model/LightVolume.shared.slh @@ -40,39 +40,24 @@ bool lightVolume_clipFragToLightVolumePoint(LightVolume lv, vec3 fragPos, out ve return (fragLightVecLen2.w <= lightVolume_getRadiusSquare(lv)); } - -bool lightVolume_clipFragToLightVolumeSpot(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2, out vec4 fragLightDirLen, out float cosSpotAngle) { - fragLightVecLen2.xyz = lightVolume_getPosition(lv) - fragPos.xyz; - fragLightVecLen2.w = dot(fragLightVecLen2.xyz, fragLightVecLen2.xyz); - - // Kill if too far from the light center - if (fragLightVecLen2.w > lightVolume_getRadiusSquare(lv)) { - return false; - } - - // Allright we re valid in the volume - fragLightDirLen.w = length(fragLightVecLen2.xyz); - fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w; - - // Kill if not in the spot light (ah ah !) - cosSpotAngle = max(-dot(fragLightDirLen.xyz, lightVolume_getDirection(lv)), 0.0); - if (cosSpotAngle < lightVolume_getSpotAngleCos(lv)) { - return false; - } - - return true; -} - -bool lightVolume_clipFragToLightVolumeSpotSide(LightVolume lv, vec4 fragLightVecLen2, out vec4 fragLightDirLen, out float cosSpotAngle) { - // Allright we re valid in the volume - fragLightDirLen.w = length(fragLightVecLen2.xyz); - fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w; - +bool lightVolume_clipFragToLightVolumeSpotSide(LightVolume lv, vec4 fragLightDirLen, out float cosSpotAngle) { // Kill if not in the spot light (ah ah !) cosSpotAngle = max(-dot(fragLightDirLen.xyz, lightVolume_getDirection(lv)), 0.0); return (cosSpotAngle >= lightVolume_getSpotAngleCos(lv)); } +bool lightVolume_clipFragToLightVolumeSpot(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2, out vec4 fragLightDirLen, out float cosSpotAngle) { + if (!lightVolume_clipFragToLightVolumePoint(lv, fragPos, fragLightVecLen2)) { + return false; + } + + // Allright we re valid in the volume + fragLightDirLen.w = length(fragLightVecLen2.xyz); + fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w; + + return lightVolume_clipFragToLightVolumeSpotSide(lv, fragLightDirLen, cosSpotAngle); +} + #endif diff --git a/libraries/render-utils/src/LightClusterGrid.slh b/libraries/render-utils/src/LightClusterGrid.slh index 3395f1be1a..14595c91a0 100644 --- a/libraries/render-utils/src/LightClusterGrid.slh +++ b/libraries/render-utils/src/LightClusterGrid.slh @@ -55,11 +55,12 @@ uniform clusterContentBuffer { int _clusterGridContent[16384]; }; -ivec2 clusterGrid_getCluster(int index) { +ivec3 clusterGrid_getCluster(int index) { int clusterDesc = _clusterGridTable[index]; - int numLights = 0xFFFF & (clusterDesc >> 16); + int numPointLights = 0xFF & (clusterDesc >> 16); + int numSpotLights = 0xFF & (clusterDesc >> 24); int contentOffset = 0xFFFF & (clusterDesc); - return ivec2(numLights, contentOffset); + return ivec3(numPointLights, numSpotLights, contentOffset); } int clusterGrid_getClusterLightId(int index, ivec2 cluster) { diff --git a/libraries/render-utils/src/LightClusters.cpp b/libraries/render-utils/src/LightClusters.cpp index cf79e30630..870dccaeea 100644 --- a/libraries/render-utils/src/LightClusters.cpp +++ b/libraries/render-utils/src/LightClusters.cpp @@ -270,7 +270,8 @@ uint32_t scanLightVolumeSphere(FrustumGrid& grid, const FrustumGrid::Planes plan void LightClusters::updateClusters() { // Clean up last info - std::vector< std::vector< LightIndex > > clusterGrid(_numClusters); + std::vector< std::vector< LightIndex > > clusterGridPoint(_numClusters); + std::vector< std::vector< LightIndex > > clusterGridSpot(_numClusters); _clusterGrid.resize(_numClusters, EMPTY_CLUSTER); uint32_t maxNumIndices = (uint32_t) _clusterContent.size(); @@ -289,6 +290,7 @@ void LightClusters::updateClusters() { auto worldOri = light->getPosition(); auto radius = light->getMaximumRadius(); + bool isSpot = light->isSpot(); // Bring into frustum eye space auto eyeOri = theFrustumGrid.frustumGrid_worldToEye(glm::vec4(worldOri, 1.0f)); @@ -395,6 +397,7 @@ void LightClusters::updateClusters() { } // now voxelize + auto& clusterGrid = (isSpot ? clusterGridSpot : clusterGridPoint); numClusterTouched += scanLightVolumeSphere(theFrustumGrid, _gridPlanes, zMin, zMax, yMin, yMax, xMin, xMax, lightId, glm::vec4(glm::vec3(eyeOri), radius), clusterGrid); } @@ -405,9 +408,13 @@ void LightClusters::updateClusters() { checkBudget = true; } uint16_t indexOffset = 0; - for (int i = 0; i < clusterGrid.size(); i++) { - auto& cluster = clusterGrid[i]; - uint16_t numLights = ((uint16_t)cluster.size()); + for (int i = 0; i < clusterGridPoint.size(); i++) { + auto& clusterPoint = clusterGridPoint[i]; + auto& clusterSpot = clusterGridSpot[i]; + + uint8_t numLightsPoint = ((uint8_t)clusterPoint.size()); + uint8_t numLightsSpot = ((uint8_t)clusterSpot.size()); + uint16_t numLights = numLightsPoint + numLightsSpot; uint16_t offset = indexOffset; // Check for overflow @@ -417,14 +424,18 @@ void LightClusters::updateClusters() { } } - _clusterGrid[i] = (uint32_t)((numLights << 16) | offset); + // _clusterGrid[i] = (uint32_t)((numLights << 16) | offset); + _clusterGrid[i] = (uint32_t)((numLightsSpot << 24) | (numLightsPoint << 16) | offset); - if (numLights) { - memcpy(_clusterContent.data() + indexOffset, cluster.data(), numLights * sizeof(LightIndex)); + if (numLightsPoint) { + memcpy(_clusterContent.data() + indexOffset, clusterPoint.data(), numLightsPoint * sizeof(LightIndex)); + indexOffset += numLightsPoint; + } + if (numLightsSpot) { + memcpy(_clusterContent.data() + indexOffset, clusterSpot.data(), numLightsSpot * sizeof(LightIndex)); + indexOffset += numLightsSpot; } - - indexOffset += numLights; } // update the buffers diff --git a/libraries/render-utils/src/LightPoint.slh b/libraries/render-utils/src/LightPoint.slh index 362aac5298..5160396e8a 100644 --- a/libraries/render-utils/src/LightPoint.slh +++ b/libraries/render-utils/src/LightPoint.slh @@ -12,16 +12,16 @@ <@func declareLightingPoint(supportScattering)@> void evalLightingPoint(out vec3 diffuse, out vec3 specular, Light light, - vec3 fragLightVec, vec3 fragEyeDir, vec3 normal, float roughness, + vec4 fragLightDirLen, vec3 fragEyeDir, vec3 normal, float roughness, float metallic, vec3 fresnel, vec3 albedo, float shadow <@if supportScattering@> , float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature <@endif@> ) { - + // Allright we re valid in the volume - float fragLightDistance = length(fragLightVec); - vec3 fragLightDir = fragLightVec / fragLightDistance; + float fragLightDistance = fragLightDirLen.w; + vec3 fragLightDir = fragLightDirLen.xyz; // Eval attenuation float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance); diff --git a/libraries/render-utils/src/LightingModel.slh b/libraries/render-utils/src/LightingModel.slh index f36b2d8131..9d5f78a581 100644 --- a/libraries/render-utils/src/LightingModel.slh +++ b/libraries/render-utils/src/LightingModel.slh @@ -82,12 +82,6 @@ float fetchSpecularBeckmann(float ndoth, float roughness) { return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0); } -float fresnelSchlickScalar(float fresnelColor, vec3 lightDir, vec3 halfDir) { - float base = 1.0 - clamp(dot(lightDir, halfDir), 0.0, 1.0); - float exponential = pow(base, 5.0); - return (exponential)+fresnelColor * (1.0 - exponential); -} - vec2 skinSpecular(vec3 N, vec3 L, vec3 V, float roughness, float intensity) { vec2 result = vec2(0.0, 1.0); float ndotl = dot(N, L); @@ -114,6 +108,11 @@ vec3 fresnelSchlickColor(vec3 fresnelColor, vec3 lightDir, vec3 halfDir) { return vec3(exponential) + fresnelColor * (1.0 - exponential); } +float fresnelSchlickScalar(float fresnelScalar, vec3 lightDir, vec3 halfDir) { + float base = 1.0 - clamp(dot(lightDir, halfDir), 0.0, 1.0); + float exponential = pow(base, 5.0); + return (exponential) + fresnelScalar * (1.0 - exponential); +} float specularDistribution(float roughness, vec3 normal, vec3 halfDir) { @@ -144,6 +143,21 @@ vec4 evalPBRShading(vec3 fragNormal, vec3 fragLightDir, vec3 fragEyeDir, float m return vec4(specular, (1.0 - metallic) * diffuse * (1 - fresnelColor.x)); } + +// Frag Shading returns the diffuse amount as W and the specular rgb as xyz +vec4 evalPBRShadingDielectric(vec3 fragNormal, vec3 fragLightDir, vec3 fragEyeDir, float roughness) { + // Diffuse Lighting + float diffuse = clamp(dot(fragNormal, fragLightDir), 0.0, 1.0); + + // Specular Lighting + vec3 halfDir = normalize(fragEyeDir + fragLightDir); + float fresnelScalar = fresnelSchlickScalar(0.03, fragLightDir, halfDir); + float power = specularDistribution(roughness, fragNormal, halfDir); + float specular = power * fresnelScalar * diffuse; + + return vec4(vec3(specular), diffuse * (1 - fresnelScalar)); +} + <@endfunc@> @@ -196,5 +210,18 @@ void evalFragShading(out vec3 diffuse, out vec3 specular, } } +void evalFragShadingSimpler(out vec3 diffuse, out vec3 specular, + vec3 fragNormal, vec3 fragLightDir, vec3 fragEyeDir, + float metallic, vec3 fresnel, float roughness, vec3 albedo +/* + ,float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature +*/ +) { + vec4 shading = evalPBRShadingDielectric(fragNormal, fragLightDir, fragEyeDir, roughness); + // vec4 shading = evalPBRShading(fragNormal, fragLightDir, fragEyeDir, metallic, fresnel, roughness); + diffuse = vec3(shading.w); + diffuse *= albedo; + specular = shading.xyz; +} <@endif@> diff --git a/libraries/render-utils/src/lightClusters_drawClusterContent.slv b/libraries/render-utils/src/lightClusters_drawClusterContent.slv index 5bf6a0bf18..8b8bdd9c94 100644 --- a/libraries/render-utils/src/lightClusters_drawClusterContent.slv +++ b/libraries/render-utils/src/lightClusters_drawClusterContent.slv @@ -53,8 +53,8 @@ void main(void) { - ivec2 cluster = clusterGrid_getCluster(gl_InstanceID); - int numLights = cluster.x; + ivec3 cluster = clusterGrid_getCluster(gl_InstanceID); + int numLights = cluster.x + cluster.y; float numLightsScale = clamp(numLights * 0.1, 0.0, 1.0); diff --git a/libraries/render-utils/src/lightClusters_drawClusterFromDepth.slf b/libraries/render-utils/src/lightClusters_drawClusterFromDepth.slf index 1820d3113b..51d0faefa7 100644 --- a/libraries/render-utils/src/lightClusters_drawClusterFromDepth.slf +++ b/libraries/render-utils/src/lightClusters_drawClusterFromDepth.slf @@ -37,8 +37,8 @@ void main(void) { ivec3 clusterPos = frustumGrid_eyeToClusterPos(clusterEyePos.xyz); - ivec2 cluster = clusterGrid_getCluster(frustumGrid_clusterToIndex(clusterPos)); - int numLights = cluster.x; + ivec3 cluster = clusterGrid_getCluster(frustumGrid_clusterToIndex(clusterPos)); + int numLights = cluster.x + cluster.y; float numLightsScale = clamp(numLights * 0.1, 0.01, 1.0); diff --git a/libraries/render-utils/src/lightClusters_drawGrid.slv b/libraries/render-utils/src/lightClusters_drawGrid.slv index 15fa8ac38a..a6590ada3f 100644 --- a/libraries/render-utils/src/lightClusters_drawGrid.slv +++ b/libraries/render-utils/src/lightClusters_drawGrid.slv @@ -54,8 +54,8 @@ void main(void) { vec4 pos = UNIT_BOX[UNIT_BOX_LINE_INDICES[gl_VertexID]]; - ivec2 cluster = clusterGrid_getCluster(gl_InstanceID); - int numLights = cluster.x; + ivec3 cluster = clusterGrid_getCluster(gl_InstanceID); + int numLights = cluster.x + cluster.y; ivec3 clusterPos = frustumGrid_indexToCluster(gl_InstanceID); diff --git a/libraries/render-utils/src/local_lights_shading.slf b/libraries/render-utils/src/local_lights_shading.slf index 3d85c0ccab..57068c4052 100644 --- a/libraries/render-utils/src/local_lights_shading.slf +++ b/libraries/render-utils/src/local_lights_shading.slf @@ -58,11 +58,13 @@ void main(void) { ivec3 clusterPos = frustumGrid_eyeToClusterPos(clusterEyePos.xyz); - ivec2 cluster = clusterGrid_getCluster(frustumGrid_clusterToIndex(clusterPos)); - int numLights = cluster.x; + ivec3 cluster = clusterGrid_getCluster(frustumGrid_clusterToIndex(clusterPos)); + int numLights = cluster.x + cluster.y; if (numLights <= 0) { discard; } + int lightClusterOffset = cluster.z; + ivec2 clusterAddress = ivec2(numLights, lightClusterOffset); ivec3 dims = frustumGrid.dims.xyz; if (clusterPos.x < 0 || clusterPos.x >= dims.x) { @@ -76,7 +78,6 @@ void main(void) { discard; } - int lightClusterOffset = cluster.y; @@ -92,48 +93,112 @@ void main(void) { vec3 fragEyeDir = normalize(fragEyeVector.xyz); int numLightTouching = 0; - for (int i = 0; i < numLights && numLightTouching < 16; i++) { + for (int i = 0; i < cluster.x; i++) { // Need the light now - int theLightIndex = clusterGrid_getClusterLightId(i, cluster); + int theLightIndex = clusterGrid_getClusterLightId(i, clusterAddress); Light light = getLight(theLightIndex); - bool isSpot = light_isSpot(light); // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space vec4 fragLightVecLen2; vec4 fragLightDirLen; - float cosSpotAngle; + if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragPos.xyz, fragLightVecLen2)) { continue; } - if (isSpot && !lightVolume_clipFragToLightVolumeSpotSide(light.volume, fragLightVecLen2, fragLightDirLen, cosSpotAngle)) { - continue; - } - if (dot(frag.normal, normalize(fragLightVecLen2.xyz)) < 0.0) { - //_fragColor.rgb += vec3(0.0, 0.0, 1.0 / 16.0); + // Allright we re in the light sphere volume + fragLightDirLen.w = length(fragLightVecLen2.xyz); + fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w; + if (dot(frag.normal, fragLightDirLen.xyz) < 0.0) { continue; } numLightTouching++; - /* - vec3 diffuse; - vec3 specular; - if (isSpot) { - evalLightingSpot(diffuse, specular, light, - fragLightDirLen.xyzw, cosSpotAngle, fragEyeDir, frag.normal, frag.roughness, - frag.metallic, frag.fresnel, frag.albedo, 1.0, - frag.scattering, midNormalCurvature, lowNormalCurvature); - } else { - evalLightingPoint(diffuse, specular, light, - fragLightVecLen2.xyz, fragEyeDir, frag.normal, frag.roughness, - frag.metallic, frag.fresnel, frag.albedo, 1.0, - frag.scattering, midNormalCurvature, lowNormalCurvature); - } + vec3 diffuse = vec3(1.0); + vec3 specular = vec3(0.1); + + // Allright we re valid in the volume + float fragLightDistance = fragLightDirLen.w; + vec3 fragLightDir = fragLightDirLen.xyz; + + // Eval attenuation + float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance); + vec3 lightEnergy = radialAttenuation * getLightIrradiance(light); + + // Eval shading + evalFragShading(diffuse, specular, frag.normal, fragLightDir, fragEyeDir, frag.metallic, frag.fresnel, frag.roughness, frag.albedo + ,frag.scattering, midNormalCurvature, lowNormalCurvature + ); + /* + evalLightingPoint(diffuse, specular, light, + fragLightDirLen.xyzw, fragEyeDir, frag.normal, frag.roughness, + frag.metallic, frag.fresnel, frag.albedo, 1.0, + frag.scattering, midNormalCurvature, lowNormalCurvature); + */ + diffuse *= lightEnergy * isDiffuseEnabled(); + specular *= lightEnergy * isSpecularEnabled(); + _fragColor.rgb += diffuse; _fragColor.rgb += specular; - */ - _fragColor.rgb += vec3(1.0/16.0, 0.0, 0.0); + } + + for (int i = cluster.x; i < numLights; i++) { + // Need the light now + int theLightIndex = clusterGrid_getClusterLightId(i, clusterAddress); + Light light = getLight(theLightIndex); + + // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space + vec4 fragLightVecLen2; + vec4 fragLightDirLen; + float cosSpotAngle; + + if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragPos.xyz, fragLightVecLen2)) { + continue; + } + + // Allright we re in the light sphere volume + fragLightDirLen.w = length(fragLightVecLen2.xyz); + fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w; + if (dot(frag.normal, fragLightDirLen.xyz) < 0.0) { + continue; + } + + // Check spot + if (!lightVolume_clipFragToLightVolumeSpotSide(light.volume, fragLightDirLen, cosSpotAngle)) { + continue; + } + + numLightTouching++; + + vec3 diffuse = vec3(1.0); + vec3 specular = vec3(0.1); + + // Allright we re valid in the volume + float fragLightDistance = fragLightDirLen.w; + vec3 fragLightDir = fragLightDirLen.xyz; + + // Eval attenuation + float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance); + float angularAttenuation = lightIrradiance_evalLightSpotAttenuation(light.irradiance, cosSpotAngle); + vec3 lightEnergy = radialAttenuation * angularAttenuation * getLightIrradiance(light); + + // Eval shading + evalFragShading(diffuse, specular, frag.normal, fragLightDir, fragEyeDir, frag.metallic, frag.fresnel, frag.roughness, frag.albedo + ,frag.scattering, midNormalCurvature, lowNormalCurvature + ); + /* evalLightingSpot(diffuse, specular, light, + fragLightDirLen.xyzw, cosSpotAngle, fragEyeDir, frag.normal, frag.roughness, + frag.metallic, frag.fresnel, frag.albedo, 1.0, + frag.scattering, midNormalCurvature, lowNormalCurvature); + */ + diffuse *= lightEnergy * isDiffuseEnabled(); + specular *= lightEnergy * isSpecularEnabled(); + + _fragColor.rgb += diffuse; + _fragColor.rgb += specular; + + // _fragColor.rgb += vec3(1.0/16.0, 0.0, 0.0); } } From 5b4829e7b6e1c905345a6ef2f7c5304833d2011e Mon Sep 17 00:00:00 2001 From: samcake Date: Fri, 30 Sep 2016 16:24:57 -0700 Subject: [PATCH 45/75] Brining back support for the ambinet lighting --- libraries/model/src/model/Light.h | 3 ++- libraries/render-utils/src/DeferredLightingEffect.cpp | 11 +++++++++-- libraries/render-utils/src/DeferredLightingEffect.h | 2 +- libraries/render-utils/src/LightingModel.slh | 8 ++++++-- libraries/render-utils/src/RenderPipelines.cpp | 1 + libraries/render/src/render/ShapePipeline.cpp | 4 +++- libraries/render/src/render/ShapePipeline.h | 2 ++ 7 files changed, 24 insertions(+), 7 deletions(-) diff --git a/libraries/model/src/model/Light.h b/libraries/model/src/model/Light.h index 893467866a..b57b8c6095 100755 --- a/libraries/model/src/model/Light.h +++ b/libraries/model/src/model/Light.h @@ -111,7 +111,8 @@ public: float getIntensity() const { return _lightSchemaBuffer->irradiance.intensity; } void setIntensity(float intensity); - bool isRanged() const { return (getType() == POINT) || (getType() == SPOT ); } + bool isRanged() const { return (getType() == POINT) || (getType() == SPOT); } + bool hasAmbient() const { return (getType() == SUN); } // FalloffRradius is the physical radius of the light sphere through which energy shines, // expressed in meters. It is used only to calculate the falloff curve of the light. diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index 01c5a81732..b1833764dd 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -45,6 +45,7 @@ struct LightLocations { int radius{ -1 }; int ambientSphere{ -1 }; int lightBufferUnit{ -1 }; + int ambientBufferUnit { -1 }; int lightIndexBufferUnit { -1 }; int texcoordFrameTransform{ -1 }; int deferredFrameTransformBuffer{ -1 }; @@ -72,6 +73,7 @@ enum DeferredShader_BufferSlot { SCATTERING_PARAMETERS_BUFFER_SLOT, LIGHTING_MODEL_BUFFER_SLOT = render::ShapePipeline::Slot::LIGHTING_MODEL, LIGHT_GPU_SLOT = render::ShapePipeline::Slot::LIGHT, + LIGHT_AMBIENT_SLOT, LIGHT_INDEX_GPU_SLOT, LIGHT_CLUSTER_GRID_FRUSTUM_GRID_SLOT, LIGHT_CLUSTER_GRID_CLUSTER_GRID_SLOT, @@ -182,13 +184,16 @@ void DeferredLightingEffect::addSpotLight(const glm::vec3& position, float radiu } } -void DeferredLightingEffect::setupKeyLightBatch(gpu::Batch& batch, int lightBufferUnit, int skyboxCubemapUnit) { +void DeferredLightingEffect::setupKeyLightBatch(gpu::Batch& batch, int lightBufferUnit, int ambientBufferUnit, int skyboxCubemapUnit) { PerformanceTimer perfTimer("DLE->setupBatch()"); auto keyLight = _allocatedLights[_globalLights.front()]; if (lightBufferUnit >= 0) { batch.setUniformBuffer(lightBufferUnit, keyLight->getLightSchemaBuffer()); } + if (keyLight->hasAmbient() && (ambientBufferUnit >= 0)) { + batch.setUniformBuffer(ambientBufferUnit, keyLight->getAmbientSchemaBuffer()); + } if (keyLight->getAmbientMap() && (skyboxCubemapUnit >= 0)) { batch.setResourceTexture(skyboxCubemapUnit, keyLight->getAmbientMap()); @@ -221,6 +226,7 @@ static gpu::ShaderPointer makeLightProgram(const char* vertSource, const char* f slotBindings.insert(gpu::Shader::Binding(std::string("lightingModelBuffer"), LIGHTING_MODEL_BUFFER_SLOT)); slotBindings.insert(gpu::Shader::Binding(std::string("subsurfaceScatteringParametersBuffer"), SCATTERING_PARAMETERS_BUFFER_SLOT)); slotBindings.insert(gpu::Shader::Binding(std::string("lightBuffer"), LIGHT_GPU_SLOT)); + slotBindings.insert(gpu::Shader::Binding(std::string("lightAmbientBuffer"), LIGHT_AMBIENT_SLOT)); slotBindings.insert(gpu::Shader::Binding(std::string("lightIndexBuffer"), LIGHT_INDEX_GPU_SLOT)); @@ -236,6 +242,7 @@ static gpu::ShaderPointer makeLightProgram(const char* vertSource, const char* f locations->texcoordFrameTransform = program->getUniforms().findLocation("texcoordFrameTransform"); locations->lightBufferUnit = program->getBuffers().findLocation("lightBuffer"); + locations->ambientBufferUnit = program->getBuffers().findLocation("lightAmbientBuffer"); locations->lightIndexBufferUnit = program->getBuffers().findLocation("lightIndexBuffer"); locations->deferredFrameTransformBuffer = program->getBuffers().findLocation("deferredFrameTransformBuffer"); locations->subsurfaceScatteringParametersBuffer = program->getBuffers().findLocation("subsurfaceScatteringParametersBuffer"); @@ -640,7 +647,7 @@ void RenderDeferredSetup::run(const render::SceneContextPointer& sceneContext, c batch._glUniform4fv(locations->texcoordFrameTransform, 1, reinterpret_cast< const float* >(&textureFrameTransform)); { // Setup the global lighting - deferredLightingEffect->setupKeyLightBatch(batch, locations->lightBufferUnit, SKYBOX_MAP_UNIT); + deferredLightingEffect->setupKeyLightBatch(batch, locations->lightBufferUnit, locations->ambientBufferUnit, SKYBOX_MAP_UNIT); } batch.draw(gpu::TRIANGLE_STRIP, 4); diff --git a/libraries/render-utils/src/DeferredLightingEffect.h b/libraries/render-utils/src/DeferredLightingEffect.h index 690d6ce5e0..1045cab30e 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.h +++ b/libraries/render-utils/src/DeferredLightingEffect.h @@ -56,7 +56,7 @@ public: float intensity = 0.5f, float falloffRadius = 0.01f, const glm::quat& orientation = glm::quat(), float exponent = 0.0f, float cutoff = PI); - void setupKeyLightBatch(gpu::Batch& batch, int lightBufferUnit, int skyboxCubemapUnit); + void setupKeyLightBatch(gpu::Batch& batch, int lightBufferUnit, int ambientBufferUnit, int skyboxCubemapUnit); // update global lighting void setGlobalLight(const model::LightPointer& light); diff --git a/libraries/render-utils/src/LightingModel.slh b/libraries/render-utils/src/LightingModel.slh index 9d5f78a581..5485224ab8 100644 --- a/libraries/render-utils/src/LightingModel.slh +++ b/libraries/render-utils/src/LightingModel.slh @@ -104,13 +104,17 @@ vec2 skinSpecular(vec3 N, vec3 L, vec3 V, float roughness, float intensity) { vec3 fresnelSchlickColor(vec3 fresnelColor, vec3 lightDir, vec3 halfDir) { float base = 1.0 - clamp(dot(lightDir, halfDir), 0.0, 1.0); - float exponential = pow(base, 5.0); + //float exponential = pow(base, 5.0); + float base2 = base * base; + float exponential = base * base2 * base2; return vec3(exponential) + fresnelColor * (1.0 - exponential); } float fresnelSchlickScalar(float fresnelScalar, vec3 lightDir, vec3 halfDir) { float base = 1.0 - clamp(dot(lightDir, halfDir), 0.0, 1.0); - float exponential = pow(base, 5.0); + //float exponential = pow(base, 5.0); + float base2 = base * base; + float exponential = base * base2 * base2; return (exponential) + fresnelScalar * (1.0 - exponential); } diff --git a/libraries/render-utils/src/RenderPipelines.cpp b/libraries/render-utils/src/RenderPipelines.cpp index e50492fd64..1f4b7ca445 100644 --- a/libraries/render-utils/src/RenderPipelines.cpp +++ b/libraries/render-utils/src/RenderPipelines.cpp @@ -78,6 +78,7 @@ void lightBatchSetter(const ShapePipeline& pipeline, gpu::Batch& batch) { if (pipeline.locations->lightBufferUnit >= 0) { DependencyManager::get()->setupKeyLightBatch(batch, pipeline.locations->lightBufferUnit, + pipeline.locations->lightAmbientBufferUnit, pipeline.locations->lightAmbientMapUnit); } } diff --git a/libraries/render/src/render/ShapePipeline.cpp b/libraries/render/src/render/ShapePipeline.cpp index 3b613e0f96..4bab517e30 100644 --- a/libraries/render/src/render/ShapePipeline.cpp +++ b/libraries/render/src/render/ShapePipeline.cpp @@ -63,6 +63,7 @@ void ShapePlumber::addPipeline(const Filter& filter, const gpu::ShaderPointer& p slotBindings.insert(gpu::Shader::Binding(std::string("occlusionMap"), Slot::MAP::OCCLUSION)); slotBindings.insert(gpu::Shader::Binding(std::string("scatteringMap"), Slot::MAP::SCATTERING)); slotBindings.insert(gpu::Shader::Binding(std::string("lightBuffer"), Slot::BUFFER::LIGHT)); + slotBindings.insert(gpu::Shader::Binding(std::string("lightAmbientBuffer"), Slot::BUFFER::LIGHT_AMBIENT_BUFFER)); slotBindings.insert(gpu::Shader::Binding(std::string("skyboxMap"), Slot::MAP::LIGHT_AMBIENT)); slotBindings.insert(gpu::Shader::Binding(std::string("normalFittingMap"), Slot::NORMAL_FITTING)); @@ -85,8 +86,9 @@ void ShapePlumber::addPipeline(const Filter& filter, const gpu::ShaderPointer& p locations->materialBufferUnit = program->getBuffers().findLocation("materialBuffer"); locations->texMapArrayBufferUnit = program->getBuffers().findLocation("texMapArrayBuffer"); locations->lightBufferUnit = program->getBuffers().findLocation("lightBuffer"); + locations->lightAmbientBufferUnit = program->getBuffers().findLocation("lightAmbientBuffer"); locations->lightAmbientMapUnit = program->getTextures().findLocation("skyboxMap"); - + ShapeKey key{filter._flags}; auto gpuPipeline = gpu::Pipeline::create(program, state); auto shapePipeline = std::make_shared(gpuPipeline, locations, batchSetter); diff --git a/libraries/render/src/render/ShapePipeline.h b/libraries/render/src/render/ShapePipeline.h index 5b60521068..e7a14d2f2b 100644 --- a/libraries/render/src/render/ShapePipeline.h +++ b/libraries/render/src/render/ShapePipeline.h @@ -201,6 +201,7 @@ public: TEXMAPARRAY, LIGHTING_MODEL, LIGHT, + LIGHT_AMBIENT_BUFFER, }; enum MAP { @@ -231,6 +232,7 @@ public: int materialBufferUnit; int texMapArrayBufferUnit; int lightBufferUnit; + int lightAmbientBufferUnit; int lightAmbientMapUnit; }; using LocationsPointer = std::shared_ptr; From 0475833e3bde695b7173bda204627e19d8a768c1 Mon Sep 17 00:00:00 2001 From: samcake Date: Fri, 30 Sep 2016 19:08:00 -0700 Subject: [PATCH 46/75] Friday night state, down to ~3.5ms in hmd --- libraries/render-utils/src/LightClusters.cpp | 21 ++----- libraries/render-utils/src/LightClusters.h | 8 +-- libraries/render-utils/src/LightingModel.slh | 63 ++++++++++++++----- .../lightClusters_drawClusterFromDepth.slf | 2 +- .../render-utils/src/local_lights_shading.slf | 17 ++--- 5 files changed, 64 insertions(+), 47 deletions(-) diff --git a/libraries/render-utils/src/LightClusters.cpp b/libraries/render-utils/src/LightClusters.cpp index e19439ba26..72f8c84c7e 100644 --- a/libraries/render-utils/src/LightClusters.cpp +++ b/libraries/render-utils/src/LightClusters.cpp @@ -183,7 +183,7 @@ float distanceToPlane(const glm::vec3& point, const glm::vec4& plane) { bool reduceSphereToPlane(const glm::vec4& sphere, const glm::vec4& plane, glm::vec4& reducedSphere) { float distance = distanceToPlane(glm::vec3(sphere), plane); - if (abs(distance) <= sphere.w) { + if (std::abs(distance) <= sphere.w) { reducedSphere = glm::vec4(sphere.x - distance * plane.x, sphere.y - distance * plane.y, sphere.z - distance * plane.z, sqrt(sphere.w * sphere.w - distance * distance)); return true; } @@ -242,7 +242,7 @@ uint32_t scanLightVolumeSphere(FrustumGrid& grid, const FrustumGrid::Planes plan auto x = xMin; for (; (x < xMax); ++x) { - auto& plane = xPlanes[x + 1]; + const auto& plane = xPlanes[x + 1]; auto testDistance = distanceToPlane(spherePoint, plane) + ySphere.w; if (testDistance >= 0.0f) { break; @@ -250,7 +250,7 @@ uint32_t scanLightVolumeSphere(FrustumGrid& grid, const FrustumGrid::Planes plan } auto xs = xMax; for (; (xs >= x); --xs) { - auto& plane = -xPlanes[xs]; + auto plane = -xPlanes[xs]; auto testDistance = distanceToPlane(spherePoint, plane) + ySphere.w; if (testDistance >= 0.0f) { break; @@ -313,27 +313,16 @@ void LightClusters::updateClusters() { continue; } - // Firt slice volume ? - /* if (zMin == -1) { - clusterGrid[0].emplace_back(lightId); - numClusterTouched++; - } */ - - // Stop there with this light if zmax is in near range - if (zMax == -1) { + // Before Range NEar just apss, range neatr == true near for now + if (zMin == -1 || zMax == -1) { continue; } - // is it a light whose origin is behind the near ? - bool behindLight = (eyeOri.z >= -theFrustumGrid.rangeNear); - // - float eyeOriLen2 = glm::length2(eyeOri); // CLamp the z range zMin = std::max(0, zMin); - // find 2D corners of the sphere in grid int xMin { 0 }; int xMax { theFrustumGrid.dims.x - 1 }; diff --git a/libraries/render-utils/src/LightClusters.h b/libraries/render-utils/src/LightClusters.h index 7b50d8864a..5c52d44ff1 100644 --- a/libraries/render-utils/src/LightClusters.h +++ b/libraries/render-utils/src/LightClusters.h @@ -20,8 +20,8 @@ class FrustumGrid { public: float frustumNear { 0.1f }; - float rangeNear { 1.0f }; - float rangeFar { 100.0f }; + float rangeNear { 0.1f }; + float rangeFar { 200.0f }; float frustumFar { 10000.0f }; glm::ivec3 dims { 16, 12, 16 }; @@ -121,8 +121,8 @@ class LightClusteringPassConfig : public render::Job::Config { Q_PROPERTY(bool freeze MEMBER freeze NOTIFY dirty) public: LightClusteringPassConfig() : render::Job::Config(true){} - float rangeNear{ 1.0f }; - float rangeFar{ 512.0f }; + float rangeNear{ 0.1f }; + float rangeFar{ 200.0f }; int dimX { 16 }; int dimY { 16 }; diff --git a/libraries/render-utils/src/LightingModel.slh b/libraries/render-utils/src/LightingModel.slh index 5485224ab8..85abf06662 100644 --- a/libraries/render-utils/src/LightingModel.slh +++ b/libraries/render-utils/src/LightingModel.slh @@ -118,10 +118,19 @@ float fresnelSchlickScalar(float fresnelScalar, vec3 lightDir, vec3 halfDir) { return (exponential) + fresnelScalar * (1.0 - exponential); } - float specularDistribution(float roughness, vec3 normal, vec3 halfDir) { float ndoth = clamp(dot(halfDir, normal), 0.0, 1.0); - float gloss2 = pow(0.001 + roughness, 4); +// float gloss2 = pow(0.001 + roughness, 4); + float gloss2 = (0.001 + roughness); + gloss2 *= gloss2; // pow 2 + gloss2 *= gloss2; // pow 4 + float denom = (ndoth * ndoth*(gloss2 - 1) + 1); + float power = gloss2 / (3.14159 * denom * denom); + return power; +} +float specularDistributionGloss(float gloss2, vec3 normal, vec3 halfDir) { + float ndoth = clamp(dot(halfDir, normal), 0.0, 1.0); +// float gloss2 = pow(0.001 + roughness, 4); float denom = (ndoth * ndoth*(gloss2 - 1) + 1); float power = gloss2 / (3.14159 * denom * denom); return power; @@ -143,23 +152,50 @@ vec4 evalPBRShading(vec3 fragNormal, vec3 fragLightDir, vec3 fragEyeDir, float m vec3 halfDir = normalize(fragEyeDir + fragLightDir); vec3 fresnelColor = fresnelSchlickColor(fresnel, fragLightDir, halfDir); float power = specularDistribution(roughness, fragNormal, halfDir); - vec3 specular = power * fresnelColor * diffuse; + vec3 specular = fresnelColor * power * diffuse; return vec4(specular, (1.0 - metallic) * diffuse * (1 - fresnelColor.x)); } // Frag Shading returns the diffuse amount as W and the specular rgb as xyz -vec4 evalPBRShadingDielectric(vec3 fragNormal, vec3 fragLightDir, vec3 fragEyeDir, float roughness) { +vec4 evalPBRShadingDielectric(vec3 fragNormal, vec3 fragLightDir, vec3 fragEyeDir, float roughness, float fresnel = 0.03) { // Diffuse Lighting float diffuse = clamp(dot(fragNormal, fragLightDir), 0.0, 1.0); // Specular Lighting vec3 halfDir = normalize(fragEyeDir + fragLightDir); - float fresnelScalar = fresnelSchlickScalar(0.03, fragLightDir, halfDir); + float fresnelScalar = fresnelSchlickScalar(fresnel, fragLightDir, halfDir); float power = specularDistribution(roughness, fragNormal, halfDir); - float specular = power * fresnelScalar * diffuse; + vec3 specular = vec3(fresnelScalar) * power * diffuse; - return vec4(vec3(specular), diffuse * (1 - fresnelScalar)); + return vec4(specular, diffuse * (1 - fresnelScalar)); +} + +vec4 evalPBRShadingMetallic(vec3 fragNormal, vec3 fragLightDir, vec3 fragEyeDir, float roughness, vec3 fresnel) { + // Diffuse Lighting + float diffuse = clamp(dot(fragNormal, fragLightDir), 0.0, 1.0); + + // Specular Lighting + vec3 halfDir = normalize(fragEyeDir + fragLightDir); + vec3 fresnelColor = fresnelSchlickColor(fresnel, fragLightDir, halfDir); + float power = specularDistribution(roughness, fragNormal, halfDir); + vec3 specular = fresnelColor * power * diffuse; + + return vec4(specular, 0.f); +} + +// Frag Shading returns the diffuse amount as W and the specular rgb as xyz +vec4 evalPBRShadingGloss(vec3 fragNormal, vec3 fragLightDir, vec3 fragEyeDir, float metallic, vec3 fresnel, float gloss2) { + // Diffuse Lighting + float diffuse = clamp(dot(fragNormal, fragLightDir), 0.0, 1.0); + + // Specular Lighting + vec3 halfDir = normalize(fragEyeDir + fragLightDir); + vec3 fresnelColor = fresnelSchlickColor(fresnel, fragLightDir, halfDir); + float power = specularDistributionGloss(gloss2, fragNormal, halfDir); + vec3 specular = fresnelColor * power * diffuse; + + return vec4(specular, (1.0 - metallic) * diffuse * (1 - fresnelColor.x)); } <@endfunc@> @@ -209,22 +245,19 @@ void evalFragShading(out vec3 diffuse, out vec3 specular, diffuse = vec3(shading.w); specular = shading.xyz; } - if (isAlbedoEnabled() > 0.0) { - diffuse *= albedo; - } + diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled()); } void evalFragShadingSimpler(out vec3 diffuse, out vec3 specular, vec3 fragNormal, vec3 fragLightDir, vec3 fragEyeDir, float metallic, vec3 fresnel, float roughness, vec3 albedo -/* + ,float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature -*/ + ) { - vec4 shading = evalPBRShadingDielectric(fragNormal, fragLightDir, fragEyeDir, roughness); - // vec4 shading = evalPBRShading(fragNormal, fragLightDir, fragEyeDir, metallic, fresnel, roughness); + vec4 shading = evalPBRShadingGloss(fragNormal, fragLightDir, fragEyeDir, metallic, fresnel, roughness); diffuse = vec3(shading.w); - diffuse *= albedo; + diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled()); specular = shading.xyz; } diff --git a/libraries/render-utils/src/lightClusters_drawClusterFromDepth.slf b/libraries/render-utils/src/lightClusters_drawClusterFromDepth.slf index 51d0faefa7..ee2e6e0ccc 100644 --- a/libraries/render-utils/src/lightClusters_drawClusterFromDepth.slf +++ b/libraries/render-utils/src/lightClusters_drawClusterFromDepth.slf @@ -39,7 +39,7 @@ void main(void) { ivec3 cluster = clusterGrid_getCluster(frustumGrid_clusterToIndex(clusterPos)); int numLights = cluster.x + cluster.y; - float numLightsScale = clamp(numLights * 0.1, 0.01, 1.0); + float numLightsScale = clamp(numLights * 0.05, 0.01, 1.0); ivec3 dims = frustumGrid.dims.xyz; diff --git a/libraries/render-utils/src/local_lights_shading.slf b/libraries/render-utils/src/local_lights_shading.slf index 57068c4052..a4f9d6f24f 100644 --- a/libraries/render-utils/src/local_lights_shading.slf +++ b/libraries/render-utils/src/local_lights_shading.slf @@ -92,6 +92,10 @@ void main(void) { vec4 fragEyeVector = invViewMat * vec4(-frag.position.xyz, 0.0); vec3 fragEyeDir = normalize(fragEyeVector.xyz); + // COmpute the rougness into gloss2 once: + float fragGloss2 = pow(frag.roughness + 0.001, 2.0); + frag.roughness = fragGloss2; + int numLightTouching = 0; for (int i = 0; i < cluster.x; i++) { // Need the light now @@ -130,12 +134,7 @@ void main(void) { evalFragShading(diffuse, specular, frag.normal, fragLightDir, fragEyeDir, frag.metallic, frag.fresnel, frag.roughness, frag.albedo ,frag.scattering, midNormalCurvature, lowNormalCurvature ); - /* - evalLightingPoint(diffuse, specular, light, - fragLightDirLen.xyzw, fragEyeDir, frag.normal, frag.roughness, - frag.metallic, frag.fresnel, frag.albedo, 1.0, - frag.scattering, midNormalCurvature, lowNormalCurvature); - */ + diffuse *= lightEnergy * isDiffuseEnabled(); specular *= lightEnergy * isSpecularEnabled(); @@ -187,11 +186,7 @@ void main(void) { evalFragShading(diffuse, specular, frag.normal, fragLightDir, fragEyeDir, frag.metallic, frag.fresnel, frag.roughness, frag.albedo ,frag.scattering, midNormalCurvature, lowNormalCurvature ); - /* evalLightingSpot(diffuse, specular, light, - fragLightDirLen.xyzw, cosSpotAngle, fragEyeDir, frag.normal, frag.roughness, - frag.metallic, frag.fresnel, frag.albedo, 1.0, - frag.scattering, midNormalCurvature, lowNormalCurvature); - */ + diffuse *= lightEnergy * isDiffuseEnabled(); specular *= lightEnergy * isSpecularEnabled(); From 35f0d4b8a2e796f25809da004c80d9f6e3c881a5 Mon Sep 17 00:00:00 2001 From: samcake Date: Sat, 1 Oct 2016 15:35:59 -0700 Subject: [PATCH 47/75] cleaning for mac --- libraries/render-utils/src/LightClusterGrid.slh | 10 ++++++++-- libraries/render-utils/src/LightClusters.cpp | 5 ++++- libraries/render-utils/src/LightingModel.slh | 2 +- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/libraries/render-utils/src/LightClusterGrid.slh b/libraries/render-utils/src/LightClusterGrid.slh index 14595c91a0..3eb3b53ccc 100644 --- a/libraries/render-utils/src/LightClusterGrid.slh +++ b/libraries/render-utils/src/LightClusterGrid.slh @@ -47,12 +47,18 @@ float projection_getFar(mat4 projection) { // end of hybrid include +<@if GLPROFILE == MAC_GL @> +#define GRID_NUM_ELEMENTS 4096 +<@else@> +#define GRID_NUM_ELEMENTS 16384 +<@endif@> + uniform clusterGridBuffer { - int _clusterGridTable[16384]; + int _clusterGridTable[GRID_NUM_ELEMENTS]; }; uniform clusterContentBuffer { - int _clusterGridContent[16384]; + int _clusterGridContent[GRID_NUM_ELEMENTS]; }; ivec3 clusterGrid_getCluster(int index) { diff --git a/libraries/render-utils/src/LightClusters.cpp b/libraries/render-utils/src/LightClusters.cpp index 72f8c84c7e..2b2f3be9d5 100644 --- a/libraries/render-utils/src/LightClusters.cpp +++ b/libraries/render-utils/src/LightClusters.cpp @@ -69,8 +69,11 @@ void FrustumGrid::generateGridPlanes(Planes& xPlanes, Planes& yPlanes, Planes& z } #include "DeferredLightingEffect.h" - +#ifdef Q_OS_MAC +const glm::uvec4 LightClusters::MAX_GRID_DIMENSIONS { 8, 8, 8, 4096 }; +#else const glm::uvec4 LightClusters::MAX_GRID_DIMENSIONS { 32, 32, 31, 16384 }; +#endif LightClusters::LightClusters() : diff --git a/libraries/render-utils/src/LightingModel.slh b/libraries/render-utils/src/LightingModel.slh index 85abf06662..7303083405 100644 --- a/libraries/render-utils/src/LightingModel.slh +++ b/libraries/render-utils/src/LightingModel.slh @@ -158,7 +158,7 @@ vec4 evalPBRShading(vec3 fragNormal, vec3 fragLightDir, vec3 fragEyeDir, float m } // Frag Shading returns the diffuse amount as W and the specular rgb as xyz -vec4 evalPBRShadingDielectric(vec3 fragNormal, vec3 fragLightDir, vec3 fragEyeDir, float roughness, float fresnel = 0.03) { +vec4 evalPBRShadingDielectric(vec3 fragNormal, vec3 fragLightDir, vec3 fragEyeDir, float roughness, float fresnel) { // Diffuse Lighting float diffuse = clamp(dot(fragNormal, fragLightDir), 0.0, 1.0); From 89717720f748304164822bafea207ea493bb7c40 Mon Sep 17 00:00:00 2001 From: samcake Date: Sat, 1 Oct 2016 16:12:45 -0700 Subject: [PATCH 48/75] CLeaning up code for Linux and Mac --- libraries/model/src/model/Light.cpp | 1 - .../src/LightClusterGrid_shared.slh | 24 +++++++++---------- libraries/render-utils/src/LightClusters.cpp | 8 +++---- 3 files changed, 16 insertions(+), 17 deletions(-) diff --git a/libraries/model/src/model/Light.cpp b/libraries/model/src/model/Light.cpp index 449054c9b2..59b57f274c 100755 --- a/libraries/model/src/model/Light.cpp +++ b/libraries/model/src/model/Light.cpp @@ -120,7 +120,6 @@ void Light::setSpotAngle(float angle) { dangle = glm::half_pi(); } auto cosAngle = cos(dangle); - auto sinAngle = sin(dangle); _spotCos = (float)std::abs(cosAngle); if (isSpot()) { diff --git a/libraries/render-utils/src/LightClusterGrid_shared.slh b/libraries/render-utils/src/LightClusterGrid_shared.slh index ec27b11a3f..37eddd087a 100644 --- a/libraries/render-utils/src/LightClusterGrid_shared.slh +++ b/libraries/render-utils/src/LightClusterGrid_shared.slh @@ -1,21 +1,21 @@ // glsl / C++ compatible source as interface for FrustrumGrid float frustumGrid_depthRampGridToVolume(float ngrid) { - if (ngrid < 0.0) + if (ngrid < 0.0f) return ngrid; // return ngrid; // return sqrt(ngrid); - return exp2(ngrid) - 1.0; + return exp2(ngrid) - 1.0f; } float frustumGrid_depthRampInverseVolumeToGrid(float nvolume) { - if (nvolume < 0.0) + if (nvolume < 0.0f) return nvolume; // return nvolume; // return nvolume * nvolume; - return log2(nvolume + 1.0); + return log2(nvolume + 1.0f); } vec3 frustumGrid_gridToVolume(vec3 pos, ivec3 dims) { - vec3 gridScale = vec3(1.0, 1.0, 1.0) / vec3(dims); + vec3 gridScale = vec3(1.0f) / vec3(dims); vec3 volumePos = pos * gridScale; volumePos.z = frustumGrid_depthRampGridToVolume(volumePos.z); return volumePos; @@ -33,9 +33,9 @@ vec3 frustumGrid_volumeToGrid(vec3 vpos, ivec3 dims) { vec4 frustumGrid_volumeToClip(vec3 vpos, float rangeNear, float rangeFar) { - vec3 ndcPos = vec3(-1.0 + 2.0 * vpos.x, -1.0 + 2.0 * vpos.y, vpos.z); + vec3 ndcPos = vec3(-1.0f + 2.0f * vpos.x, -1.0f + 2.0f * vpos.y, vpos.z); float depth = rangeNear * (1 - ndcPos.z) + rangeFar * (ndcPos.z); - vec4 clipPos = vec4(ndcPos.x * depth, ndcPos.y * depth, 1.0, depth); + vec4 clipPos = vec4(ndcPos.x * depth, ndcPos.y * depth, 1.0f, depth); return clipPos; } @@ -64,7 +64,7 @@ vec3 frustumGrid_eyeToVolume(vec3 epos, mat4 projection, float rangeNear, float -epos.z); vec4 ndcPos = clipPos / clipPos.w; - vec3 volumePos = vec3(0.5 * (ndcPos.x + 1.0), 0.5 * (ndcPos.y + 1.0), (clipPos.w - rangeNear) / (rangeFar - rangeNear)); + vec3 volumePos = vec3(0.5f * (ndcPos.x + 1.0f), 0.5f * (ndcPos.y + 1.0f), (clipPos.w - rangeNear) / (rangeFar - rangeNear)); return volumePos; } @@ -145,28 +145,28 @@ ivec3 frustumGrid_eyeToClusterPos(vec3 eyePos) { } int frustumGrid_eyeToClusterDirH(vec3 eyeDir) { - if (eyeDir.z >= 0.0) { + if (eyeDir.z >= 0.0f) { return (eyeDir.x > 0 ? frustumGrid.dims.x : -1); } float eyeDepth = -eyeDir.z; float nclipDir = eyeDir.x / eyeDepth; float ndcDir = nclipDir * frustumGrid.eyeToGridProj[0][0] - frustumGrid.eyeToGridProj[2][0]; - float volumeDir = 0.5 * (ndcDir + 1.0); + float volumeDir = 0.5f * (ndcDir + 1.0f); float gridPos = volumeDir * float(frustumGrid.dims.x); return int(gridPos); } int frustumGrid_eyeToClusterDirV(vec3 eyeDir) { - if (eyeDir.z >= 0.0) { + if (eyeDir.z >= 0.0f) { return (eyeDir.y > 0 ? frustumGrid.dims.y : -1); } float eyeDepth = -eyeDir.z; float nclipDir = eyeDir.y / eyeDepth; float ndcDir = nclipDir * frustumGrid.eyeToGridProj[1][1] - frustumGrid.eyeToGridProj[2][1]; - float volumeDir = 0.5 * (ndcDir + 1.0); + float volumeDir = 0.5f * (ndcDir + 1.0f); float gridPos = volumeDir * float(frustumGrid.dims.y); return int(gridPos); diff --git a/libraries/render-utils/src/LightClusters.cpp b/libraries/render-utils/src/LightClusters.cpp index 2b2f3be9d5..77e0d4d354 100644 --- a/libraries/render-utils/src/LightClusters.cpp +++ b/libraries/render-utils/src/LightClusters.cpp @@ -46,8 +46,8 @@ void FrustumGrid::generateGridPlanes(Planes& xPlanes, Planes& yPlanes, Planes& z yPlanes.resize(dims.y + 1); zPlanes.resize(dims.z + 1); - float centerY = float(dims.y) * 0.5; - float centerX = float(dims.x) * 0.5; + float centerY = float(dims.y) * 0.5f; + float centerX = float(dims.x) * 0.5f; for (int z = 0; z < (int) zPlanes.size(); z++) { ivec3 pos(0, 0, z); @@ -400,7 +400,7 @@ void LightClusters::updateClusters() { checkBudget = true; } uint16_t indexOffset = 0; - for (int i = 0; i < clusterGridPoint.size(); i++) { + for (int i = 0; i < (int) clusterGridPoint.size(); i++) { auto& clusterPoint = clusterGridPoint[i]; auto& clusterSpot = clusterGridSpot[i]; @@ -417,7 +417,7 @@ void LightClusters::updateClusters() { } // _clusterGrid[i] = (uint32_t)((numLights << 16) | offset); - _clusterGrid[i] = (uint32_t)((numLightsSpot << 24) | (numLightsPoint << 16) | offset); + _clusterGrid[i] = (uint32_t)((0xFF000000 & (numLightsSpot << 24)) | (0x00FF0000 & (numLightsPoint << 16)) | (0x0000FFFF & offset)); if (numLightsPoint) { From bdf2738f21bc48f61af473bf88e272edd1a3ee88 Mon Sep 17 00:00:00 2001 From: samcake Date: Sat, 1 Oct 2016 17:25:26 -0700 Subject: [PATCH 49/75] One more fix for linux build --- libraries/render-utils/src/LightClusterGrid_shared.slh | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libraries/render-utils/src/LightClusterGrid_shared.slh b/libraries/render-utils/src/LightClusterGrid_shared.slh index 37eddd087a..7308084b1e 100644 --- a/libraries/render-utils/src/LightClusterGrid_shared.slh +++ b/libraries/render-utils/src/LightClusterGrid_shared.slh @@ -1,14 +1,14 @@ // glsl / C++ compatible source as interface for FrustrumGrid float frustumGrid_depthRampGridToVolume(float ngrid) { - if (ngrid < 0.0f) - return ngrid; + //if (ngrid < 0.0f) + // return ngrid; // return ngrid; // return sqrt(ngrid); - return exp2(ngrid) - 1.0f; + return exp2(float(ngrid)) - 1.0f; } float frustumGrid_depthRampInverseVolumeToGrid(float nvolume) { - if (nvolume < 0.0f) - return nvolume; + //if (nvolume < 0.0f) + // return nvolume; // return nvolume; // return nvolume * nvolume; return log2(nvolume + 1.0f); From bd4268ee18d071b2a24adb5a99671d3e1873a2d3 Mon Sep 17 00:00:00 2001 From: sam Date: Sat, 1 Oct 2016 17:59:37 -0700 Subject: [PATCH 50/75] Try to fix the exp2 float version for linux --- libraries/render-utils/src/LightClusterGrid_shared.slh | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/libraries/render-utils/src/LightClusterGrid_shared.slh b/libraries/render-utils/src/LightClusterGrid_shared.slh index 7308084b1e..285b80c229 100644 --- a/libraries/render-utils/src/LightClusterGrid_shared.slh +++ b/libraries/render-utils/src/LightClusterGrid_shared.slh @@ -1,10 +1,16 @@ // glsl / C++ compatible source as interface for FrustrumGrid +#if defined(Q_OS_LINUX) +#define float_exp2 exp2f +#else +#define float_exp2 exp2 +#endif + float frustumGrid_depthRampGridToVolume(float ngrid) { //if (ngrid < 0.0f) // return ngrid; // return ngrid; // return sqrt(ngrid); - return exp2(float(ngrid)) - 1.0f; + return float_exp2(ngrid) - 1.0f; } float frustumGrid_depthRampInverseVolumeToGrid(float nvolume) { //if (nvolume < 0.0f) From 9a492b3a8889effeb40d62d47df1414ffc49be4a Mon Sep 17 00:00:00 2001 From: sam Date: Sun, 2 Oct 2016 03:43:55 -0700 Subject: [PATCH 51/75] refining the voxelizatoion, tracking one bug where light flickers --- .../src/gpu/gl45/GL45BackendTexture.cpp | 2 +- .../src/LightClusterGrid_shared.slh | 8 ++--- libraries/render-utils/src/LightClusters.cpp | 31 ++++++++++++------- libraries/render-utils/src/LightingModel.slh | 26 +++++++++++++--- .../render-utils/src/local_lights_shading.slf | 23 ++++++++------ 5 files changed, 58 insertions(+), 32 deletions(-) diff --git a/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp b/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp index 3e6e53ffc3..061da3e397 100644 --- a/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp +++ b/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp @@ -513,7 +513,7 @@ void GL45Texture::stripToMip(uint16_t newMinMip) { syncSampler(); size_t oldSize = _size; updateSize(); - Q_ASSERT(_size > oldSize); + // Q_ASSERT(_size > oldSize); // Re-insert into the texture-by-mips map if appropriate diff --git a/libraries/render-utils/src/LightClusterGrid_shared.slh b/libraries/render-utils/src/LightClusterGrid_shared.slh index 285b80c229..d5bde79056 100644 --- a/libraries/render-utils/src/LightClusterGrid_shared.slh +++ b/libraries/render-utils/src/LightClusterGrid_shared.slh @@ -6,16 +6,12 @@ #endif float frustumGrid_depthRampGridToVolume(float ngrid) { - //if (ngrid < 0.0f) - // return ngrid; - // return ngrid; + // return ngrid; // return sqrt(ngrid); return float_exp2(ngrid) - 1.0f; } float frustumGrid_depthRampInverseVolumeToGrid(float nvolume) { - //if (nvolume < 0.0f) - // return nvolume; - // return nvolume; + // return nvolume; // return nvolume * nvolume; return log2(nvolume + 1.0f); } diff --git a/libraries/render-utils/src/LightClusters.cpp b/libraries/render-utils/src/LightClusters.cpp index 77e0d4d354..cbe5f17856 100644 --- a/libraries/render-utils/src/LightClusters.cpp +++ b/libraries/render-utils/src/LightClusters.cpp @@ -202,7 +202,7 @@ uint32_t scanLightVolumeBox(FrustumGrid& grid, const FrustumGrid::Planes planes[ for (auto z = zMin; (z <= zMax); z++) { for (auto y = yMin; (y <= yMax); y++) { for (auto x = xMin; (x <= xMax); x++) { - auto index = 1 + x + gridPosToOffset.y * y + gridPosToOffset.z * z; + auto index = x + gridPosToOffset.y * y + gridPosToOffset.z * z; clusterGrid[index].emplace_back(lightId); numClustersTouched++; } @@ -220,12 +220,15 @@ uint32_t scanLightVolumeSphere(FrustumGrid& grid, const FrustumGrid::Planes plan const auto& yPlanes = planes[1]; const auto& zPlanes = planes[2]; - int center_z = grid.frustumGrid_eyeDepthToClusterLayer(eyePosRadius.z); - int center_y = (yMax + yMin) >> 1; + // FInd the light origin cluster + auto centerCluster = grid.frustumGrid_eyeToClusterPos(glm::vec3(eyePosRadius)); + int center_z = centerCluster.z; + int center_y = centerCluster.y; + for (auto z = zMin; (z <= zMax); z++) { auto zSphere = eyePosRadius; if (z != center_z) { - auto& plane = (z < center_z) ? zPlanes[z + 1] : -zPlanes[z]; + auto plane = (z < center_z) ? zPlanes[z + 1] : -zPlanes[z]; if (!reduceSphereToPlane(zSphere, plane, zSphere)) { // pass this slice! continue; @@ -234,7 +237,7 @@ uint32_t scanLightVolumeSphere(FrustumGrid& grid, const FrustumGrid::Planes plan for (auto y = yMin; (y <= yMax); y++) { auto ySphere = zSphere; if (y != center_y) { - auto& plane = (y < center_y) ? yPlanes[y + 1] : -yPlanes[y]; + auto plane = (y < center_y) ? yPlanes[y + 1] : -yPlanes[y]; if (!reduceSphereToPlane(ySphere, plane, ySphere)) { // pass this slice! continue; @@ -262,8 +265,12 @@ uint32_t scanLightVolumeSphere(FrustumGrid& grid, const FrustumGrid::Planes plan for (; (x <= xs); x++) { auto index = grid.frustumGrid_clusterToIndex(ivec3(x, y, z)); - clusterGrid[index].emplace_back(lightId); - numClustersTouched++; + if (index < (int) clusterGrid.size()) { + clusterGrid[index].emplace_back(lightId); + numClustersTouched++; + } else { + qDebug() << "WARNING: LightClusters::scanLightVolumeSphere invalid index found ? numClusters = " << clusterGrid.size() << " index = " << index << " found from cluster xyz = " << x << " " << y << " " << z; + } } } } @@ -324,7 +331,7 @@ void LightClusters::updateClusters() { // CLamp the z range zMin = std::max(0, zMin); - + // zMax = std::min(zMax, theFrustumGrid.dims.z); // find 2D corners of the sphere in grid int xMin { 0 }; @@ -362,7 +369,7 @@ void LightClusters::updateClusters() { auto rc = theFrustumGrid.frustumGrid_eyeToClusterDirH(rightDir); xMin = std::max(xMin, lc); - xMax = std::max(0, std::min(rc, xMax)); + xMax = std::min(rc, xMax); } if ((eyeOriLen2V > radius2)) { @@ -385,12 +392,14 @@ void LightClusters::updateClusters() { auto tc = theFrustumGrid.frustumGrid_eyeToClusterDirV(topDir); yMin = std::max(yMin, bc); - yMax = std::max(yMin, std::min(tc, yMax)); + yMax =std::min(tc, yMax); } // now voxelize auto& clusterGrid = (isSpot ? clusterGridSpot : clusterGridPoint); - numClusterTouched += scanLightVolumeSphere(theFrustumGrid, _gridPlanes, zMin, zMax, yMin, yMax, xMin, xMax, lightId, glm::vec4(glm::vec3(eyeOri), radius), clusterGrid); + // numClusterTouched += scanLightVolumeSphere(theFrustumGrid, _gridPlanes, zMin, zMax, yMin, yMax, xMin, xMax, lightId, glm::vec4(glm::vec3(eyeOri), radius), clusterGrid); + numClusterTouched += scanLightVolumeBox(theFrustumGrid, _gridPlanes, zMin, zMax, yMin, yMax, xMin, xMax, lightId, glm::vec4(glm::vec3(eyeOri), radius), clusterGrid); + } // Lights have been gathered now reexpress in terms of 2 sequential buffers diff --git a/libraries/render-utils/src/LightingModel.slh b/libraries/render-utils/src/LightingModel.slh index 7303083405..1f5a16afaa 100644 --- a/libraries/render-utils/src/LightingModel.slh +++ b/libraries/render-utils/src/LightingModel.slh @@ -241,21 +241,37 @@ void evalFragShading(out vec3 diffuse, out vec3 specular, diffuse *= specularBrdf.y; specular = vec3(specularBrdf.x); } else { - vec4 shading = evalPBRShading(fragNormal, fragLightDir, fragEyeDir, metallic, fresnel, roughness); + vec4 shading = evalPBRShadingGloss(fragNormal, fragLightDir, fragEyeDir, metallic, fresnel, roughness); diffuse = vec3(shading.w); specular = shading.xyz; } diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled()); } -void evalFragShadingSimpler(out vec3 diffuse, out vec3 specular, + +void evalFragShadingScattering(out vec3 diffuse, out vec3 specular, vec3 fragNormal, vec3 fragLightDir, vec3 fragEyeDir, float metallic, vec3 fresnel, float roughness, vec3 albedo - ,float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature - ) { - vec4 shading = evalPBRShadingGloss(fragNormal, fragLightDir, fragEyeDir, metallic, fresnel, roughness); + vec3 brdf = evalSkinBRDF(fragLightDir, fragNormal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w); + float NdotL = clamp(dot(fragNormal, fragLightDir), 0.0, 1.0); + diffuse = mix(vec3(NdotL), brdf, scattering); + + // Specular Lighting + vec3 halfDir = normalize(fragEyeDir + fragLightDir); + vec2 specularBrdf = skinSpecular(fragNormal, fragLightDir, fragEyeDir, roughness, 1.0); + + diffuse *= specularBrdf.y; + specular = vec3(specularBrdf.x); + diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled()); +} + +void evalFragShadingGloss(out vec3 diffuse, out vec3 specular, + vec3 fragNormal, vec3 fragLightDir, vec3 fragEyeDir, + float metallic, vec3 fresnel, float gloss, vec3 albedo +) { + vec4 shading = evalPBRShadingGloss(fragNormal, fragLightDir, fragEyeDir, metallic, fresnel, gloss); diffuse = vec3(shading.w); diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled()); specular = shading.xyz; diff --git a/libraries/render-utils/src/local_lights_shading.slf b/libraries/render-utils/src/local_lights_shading.slf index a4f9d6f24f..128d128188 100644 --- a/libraries/render-utils/src/local_lights_shading.slf +++ b/libraries/render-utils/src/local_lights_shading.slf @@ -31,6 +31,7 @@ <@include LightClusterGrid.slh@> + in vec2 _texCoord0; out vec4 _fragColor; @@ -94,7 +95,7 @@ void main(void) { // COmpute the rougness into gloss2 once: float fragGloss2 = pow(frag.roughness + 0.001, 2.0); - frag.roughness = fragGloss2; + bool withScattering = (frag.scattering * isScatteringEnabled() > 0.0); int numLightTouching = 0; for (int i = 0; i < cluster.x; i++) { @@ -131,9 +132,12 @@ void main(void) { vec3 lightEnergy = radialAttenuation * getLightIrradiance(light); // Eval shading - evalFragShading(diffuse, specular, frag.normal, fragLightDir, fragEyeDir, frag.metallic, frag.fresnel, frag.roughness, frag.albedo - ,frag.scattering, midNormalCurvature, lowNormalCurvature - ); + if (withScattering) { + evalFragShadingScattering(diffuse, specular, frag.normal, fragLightDir, fragEyeDir, frag.metallic, frag.fresnel, frag.roughness, frag.albedo + ,frag.scattering, midNormalCurvature, lowNormalCurvature ); + } else { + evalFragShadingGloss(diffuse, specular, frag.normal, fragLightDir, fragEyeDir, frag.metallic, frag.fresnel, fragGloss2, frag.albedo); + } diffuse *= lightEnergy * isDiffuseEnabled(); specular *= lightEnergy * isSpecularEnabled(); @@ -183,17 +187,18 @@ void main(void) { vec3 lightEnergy = radialAttenuation * angularAttenuation * getLightIrradiance(light); // Eval shading - evalFragShading(diffuse, specular, frag.normal, fragLightDir, fragEyeDir, frag.metallic, frag.fresnel, frag.roughness, frag.albedo - ,frag.scattering, midNormalCurvature, lowNormalCurvature - ); + if (withScattering) { + evalFragShadingScattering(diffuse, specular, frag.normal, fragLightDir, fragEyeDir, frag.metallic, frag.fresnel, frag.roughness, frag.albedo + ,frag.scattering, midNormalCurvature, lowNormalCurvature ); + } else { + evalFragShadingGloss(diffuse, specular, frag.normal, fragLightDir, fragEyeDir, frag.metallic, frag.fresnel, fragGloss2, frag.albedo); + } diffuse *= lightEnergy * isDiffuseEnabled(); specular *= lightEnergy * isSpecularEnabled(); _fragColor.rgb += diffuse; _fragColor.rgb += specular; - - // _fragColor.rgb += vec3(1.0/16.0, 0.0, 0.0); } } From 6f2452815c04b6c265c42bd59ff25f27444b98f4 Mon Sep 17 00:00:00 2001 From: sam Date: Mon, 3 Oct 2016 00:08:30 -0700 Subject: [PATCH 52/75] pass the visibility of the enitity to the LightPaylkoad correctly, clean up the ambient shader --- libraries/audio/src/AudioInjector.cpp | 2 +- .../src/RenderableLightEntityItem.cpp | 3 ++ .../src/gpu/gl45/GL45BackendTexture.cpp | 3 -- libraries/model/src/model/Light.slh | 32 ++++------------- .../src/DeferredLightingEffect.cpp | 36 ++++++++++++++----- .../render-utils/src/DeferredLightingEffect.h | 1 + libraries/render-utils/src/LightAmbient.slh | 1 - libraries/render-utils/src/LightPayload.cpp | 13 +++++-- libraries/render-utils/src/LightPayload.h | 6 +++- 9 files changed, 54 insertions(+), 43 deletions(-) diff --git a/libraries/audio/src/AudioInjector.cpp b/libraries/audio/src/AudioInjector.cpp index 43bff3ccce..6f6534e2d2 100644 --- a/libraries/audio/src/AudioInjector.cpp +++ b/libraries/audio/src/AudioInjector.cpp @@ -26,7 +26,7 @@ #include "SoundCache.h" #include "AudioSRC.h" -//int audioInjectorPtrMetaTypeId = qRegisterMetaType(); +int audioInjectorPtrMetaTypeId = qRegisterMetaType(); AbstractAudioInterface* AudioInjector::_localAudioInterface{ nullptr }; diff --git a/libraries/entities-renderer/src/RenderableLightEntityItem.cpp b/libraries/entities-renderer/src/RenderableLightEntityItem.cpp index 9f97b7f405..4ae2da295f 100644 --- a/libraries/entities-renderer/src/RenderableLightEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableLightEntityItem.cpp @@ -140,6 +140,9 @@ void RenderableLightEntityItem::updateLightFromEntity(render::PendingChanges& pe void RenderableLightEntityItem::updateRenderItemFromEntity(LightPayload* lightPayload) { auto entity = this; + + lightPayload->setVisible(entity->getVisible()); + auto light = lightPayload->editLight(); light->setPosition(entity->getPosition()); light->setOrientation(entity->getRotation()); diff --git a/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp b/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp index 061da3e397..821d4d14c9 100644 --- a/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp +++ b/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp @@ -511,10 +511,7 @@ void GL45Texture::stripToMip(uint16_t newMinMip) { _minMip = newMinMip; // Re-sync the sampler to force access to the new mip level syncSampler(); - size_t oldSize = _size; updateSize(); - // Q_ASSERT(_size > oldSize); - // Re-insert into the texture-by-mips map if appropriate mipLevels = usedMipLevels(); diff --git a/libraries/model/src/model/Light.slh b/libraries/model/src/model/Light.slh index 78fa11416d..d405848d43 100644 --- a/libraries/model/src/model/Light.slh +++ b/libraries/model/src/model/Light.slh @@ -11,13 +11,10 @@ <@if not MODEL_LIGHT_SLH@> <@def MODEL_LIGHT_SLH@> -<@include model/SphericalHarmonics.shared.slh@> <@include model/LightVolume.shared.slh@> <@include model/LightIrradiance.shared.slh@> // NOw lets define Light - - struct Light { LightVolume volume; LightIrradiance irradiance; @@ -28,38 +25,23 @@ bool light_isSpot(Light l) { return lightVolume_isSpot(l.volume); } vec3 getLightPosition(Light l) { return lightVolume_getPosition(l.volume); } vec3 getLightDirection(Light l) { return lightVolume_getDirection(l.volume); } - vec3 getLightColor(Light l) { return lightIrradiance_getColor(l.irradiance); } float getLightIntensity(Light l) { return lightIrradiance_getIntensity(l.irradiance); } vec3 getLightIrradiance(Light l) { return lightIrradiance_getIrradiance(l.irradiance); } - - - - - - +// AMbient lighting needs extra info provided from a different Buffer +<@include model/SphericalHarmonics.shared.slh@> +// Light Ambient struct LightAmbient { vec4 _ambient; SphericalHarmonics _ambientSphere; }; -SphericalHarmonics getLightAmbientSphere(LightAmbient l) { - return l._ambientSphere; -} +SphericalHarmonics getLightAmbientSphere(LightAmbient l) { return l._ambientSphere; } - -float getLightAmbientIntensity(LightAmbient l) { return l._ambient.w; } - - -bool getLightHasAmbientMap(LightAmbient l) { - return l._ambient.x > 0; - // return l._control.x > 0; -} - -float getLightAmbientMapNumMips(LightAmbient l) { - return l._ambient.x; -} +float getLightAmbientIntensity(LightAmbient l) { return l._ambient.x; } +bool getLightHasAmbientMap(LightAmbient l) { return l._ambient.y > 0; } +float getLightAmbientMapNumMips(LightAmbient l) { return l._ambient.y; } <@func declareLightBuffer(N)@> diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index b1833764dd..ace969563e 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -43,7 +43,6 @@ using namespace render; struct LightLocations { int radius{ -1 }; - int ambientSphere{ -1 }; int lightBufferUnit{ -1 }; int ambientBufferUnit { -1 }; int lightIndexBufferUnit { -1 }; @@ -199,6 +198,22 @@ void DeferredLightingEffect::setupKeyLightBatch(gpu::Batch& batch, int lightBuff batch.setResourceTexture(skyboxCubemapUnit, keyLight->getAmbientMap()); } } + +void DeferredLightingEffect::unsetKeyLightBatch(gpu::Batch& batch, int lightBufferUnit, int ambientBufferUnit, int skyboxCubemapUnit) { + auto keyLight = _allocatedLights[_globalLights.front()]; + + if (lightBufferUnit >= 0) { + batch.setUniformBuffer(lightBufferUnit, nullptr); + } + if (keyLight->hasAmbient() && (ambientBufferUnit >= 0)) { + batch.setUniformBuffer(ambientBufferUnit, nullptr); + } + + if (keyLight->getAmbientMap() && (skyboxCubemapUnit >= 0)) { + batch.setResourceTexture(skyboxCubemapUnit, nullptr); + } +} + static gpu::ShaderPointer makeLightProgram(const char* vertSource, const char* fragSource, LightLocationsPtr& locations) { auto VS = gpu::Shader::createVertex(std::string(vertSource)); auto PS = gpu::Shader::createPixel(std::string(fragSource)); @@ -237,7 +252,6 @@ static gpu::ShaderPointer makeLightProgram(const char* vertSource, const char* f gpu::Shader::makeProgram(*program, slotBindings); locations->radius = program->getUniforms().findLocation("radius"); - locations->ambientSphere = program->getUniforms().findLocation("ambientSphere.L00"); locations->texcoordFrameTransform = program->getUniforms().findLocation("texcoordFrameTransform"); @@ -646,15 +660,14 @@ void RenderDeferredSetup::run(const render::SceneContextPointer& sceneContext, c auto textureFrameTransform = gpu::Framebuffer::evalSubregionTexcoordTransformCoefficients(deferredFramebuffer->getFrameSize(), args->_viewport); batch._glUniform4fv(locations->texcoordFrameTransform, 1, reinterpret_cast< const float* >(&textureFrameTransform)); - { // Setup the global lighting - deferredLightingEffect->setupKeyLightBatch(batch, locations->lightBufferUnit, locations->ambientBufferUnit, SKYBOX_MAP_UNIT); - } - + // Setup the global lighting + deferredLightingEffect->setupKeyLightBatch(batch, locations->lightBufferUnit, locations->ambientBufferUnit, SKYBOX_MAP_UNIT); + batch.draw(gpu::TRIANGLE_STRIP, 4); - if (keyLight->getAmbientMap()) { - batch.setResourceTexture(SKYBOX_MAP_UNIT, nullptr); - } + deferredLightingEffect->unsetKeyLightBatch(batch, locations->lightBufferUnit, locations->ambientBufferUnit, SKYBOX_MAP_UNIT); + + batch.setResourceTexture(SHADOW_MAP_UNIT, nullptr); } } @@ -806,6 +819,11 @@ void RenderDeferredCleanup::run(const render::SceneContextPointer& sceneContext, batch.setUniformBuffer(SCATTERING_PARAMETERS_BUFFER_SLOT, nullptr); // batch.setUniformBuffer(LIGHTING_MODEL_BUFFER_SLOT, nullptr); batch.setUniformBuffer(DEFERRED_FRAME_TRANSFORM_BUFFER_SLOT, nullptr); + + batch.setUniformBuffer(LIGHT_CLUSTER_GRID_FRUSTUM_GRID_SLOT, nullptr); + batch.setUniformBuffer(LIGHT_CLUSTER_GRID_CLUSTER_GRID_SLOT, nullptr); + batch.setUniformBuffer(LIGHT_CLUSTER_GRID_CLUSTER_CONTENT_SLOT, nullptr); + } auto deferredLightingEffect = DependencyManager::get(); diff --git a/libraries/render-utils/src/DeferredLightingEffect.h b/libraries/render-utils/src/DeferredLightingEffect.h index 1045cab30e..9462dbcc4e 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.h +++ b/libraries/render-utils/src/DeferredLightingEffect.h @@ -57,6 +57,7 @@ public: const glm::quat& orientation = glm::quat(), float exponent = 0.0f, float cutoff = PI); void setupKeyLightBatch(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); diff --git a/libraries/render-utils/src/LightAmbient.slh b/libraries/render-utils/src/LightAmbient.slh index ecb8fa0ae5..98f043081e 100644 --- a/libraries/render-utils/src/LightAmbient.slh +++ b/libraries/render-utils/src/LightAmbient.slh @@ -74,7 +74,6 @@ void evalLightingAmbient(out vec3 diffuse, out vec3 specular, LightAmbient ambie <@endif@> ) { - // Diffuse from ambient diffuse = (1 - metallic) * sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), normal).xyz; diff --git a/libraries/render-utils/src/LightPayload.cpp b/libraries/render-utils/src/LightPayload.cpp index 8f7b893f6a..5f58677efe 100644 --- a/libraries/render-utils/src/LightPayload.cpp +++ b/libraries/render-utils/src/LightPayload.cpp @@ -16,7 +16,12 @@ namespace render { template <> const ItemKey payloadGetKey(const LightPayload::Pointer& payload) { - return ItemKey::Builder::light(); + ItemKey::Builder builder; + builder.withTypeLight(); + if (!payload || !payload->isVisible()) { + builder.withInvisible(); + } + return builder.build(); } template <> const Item::Bound payloadGetBound(const LightPayload::Pointer& payload) { @@ -63,7 +68,9 @@ void LightPayload::render(RenderArgs* args) { _needUpdate = false; } - // FInally, push the light visible in the frame - _stage->_currentFrame.pushLight(_index, _light->getType()); + if (isVisible()) { + // FInally, push the light visible in the frame + _stage->_currentFrame.pushLight(_index, _light->getType()); + } } diff --git a/libraries/render-utils/src/LightPayload.h b/libraries/render-utils/src/LightPayload.h index fba4ff15cb..6b5fe83f07 100644 --- a/libraries/render-utils/src/LightPayload.h +++ b/libraries/render-utils/src/LightPayload.h @@ -27,13 +27,17 @@ public: model::LightPointer editLight() { _needUpdate = true; return _light; } render::Item::Bound& editBound() { _needUpdate = true; return _bound; } - + + void setVisible(bool visible) { _isVisible = visible; } + bool isVisible() const { return _isVisible; } + protected: model::LightPointer _light; render::Item::Bound _bound; LightStagePointer _stage; LightStage::Index _index { LightStage::INVALID_INDEX }; bool _needUpdate { true }; + bool _isVisible{ true }; }; namespace render { From deab1db39a7a2cdc6bef174f7c2b954483695b28 Mon Sep 17 00:00:00 2001 From: sam Date: Mon, 3 Oct 2016 02:53:41 -0700 Subject: [PATCH 53/75] FIxed the flickering bug and make a better debuging view to control the overlap --- libraries/render-utils/src/LightClusters.cpp | 62 ++++++++++---- .../src/lightClusters_drawClusterContent.slf | 84 ++++++++++++++++++- .../render-utils/src/local_lights_shading.slf | 3 - 3 files changed, 126 insertions(+), 23 deletions(-) diff --git a/libraries/render-utils/src/LightClusters.cpp b/libraries/render-utils/src/LightClusters.cpp index cbe5f17856..2eda0f95a2 100644 --- a/libraries/render-utils/src/LightClusters.cpp +++ b/libraries/render-utils/src/LightClusters.cpp @@ -27,6 +27,10 @@ enum LightClusterGridShader_MapSlot { DEFERRED_BUFFER_LINEAR_DEPTH_UNIT = 0, + DEFERRED_BUFFER_COLOR_UNIT, + DEFERRED_BUFFER_NORMAL_UNIT, + DEFERRED_BUFFER_EMISSIVE_UNIT, + DEFERRED_BUFFER_DEPTH_UNIT, }; enum LightClusterGridShader_BufferSlot { @@ -324,7 +328,7 @@ void LightClusters::updateClusters() { } // Before Range NEar just apss, range neatr == true near for now - if (zMin == -1 || zMax == -1) { + if ((zMin == -1) && (zMax == -1)) { continue; } @@ -397,8 +401,8 @@ void LightClusters::updateClusters() { // now voxelize auto& clusterGrid = (isSpot ? clusterGridSpot : clusterGridPoint); - // numClusterTouched += scanLightVolumeSphere(theFrustumGrid, _gridPlanes, zMin, zMax, yMin, yMax, xMin, xMax, lightId, glm::vec4(glm::vec3(eyeOri), radius), clusterGrid); - numClusterTouched += scanLightVolumeBox(theFrustumGrid, _gridPlanes, zMin, zMax, yMin, yMax, xMin, xMax, lightId, glm::vec4(glm::vec3(eyeOri), radius), clusterGrid); + numClusterTouched += scanLightVolumeSphere(theFrustumGrid, _gridPlanes, zMin, zMax, yMin, yMax, xMin, xMax, lightId, glm::vec4(glm::vec3(eyeOri), radius), clusterGrid); + // numClusterTouched += scanLightVolumeBox(theFrustumGrid, _gridPlanes, zMin, zMax, yMin, yMax, xMin, xMax, lightId, glm::vec4(glm::vec3(eyeOri), radius), clusterGrid); } @@ -539,6 +543,7 @@ const gpu::PipelinePointer DebugLightClusters::getDrawClusterFromDepthPipeline() slotBindings.insert(gpu::Shader::Binding(std::string("clusterGridBuffer"), LIGHT_CLUSTER_GRID_CLUSTER_GRID_SLOT)); slotBindings.insert(gpu::Shader::Binding(std::string("clusterContentBuffer"), LIGHT_CLUSTER_GRID_CLUSTER_CONTENT_SLOT)); slotBindings.insert(gpu::Shader::Binding(std::string("linearZeyeMap"), DEFERRED_BUFFER_LINEAR_DEPTH_UNIT)); + slotBindings.insert(gpu::Shader::Binding(std::string("cameraCorrectionBuffer"), CAMERA_CORRECTION_BUFFER_SLOT)); slotBindings.insert(gpu::Shader::Binding(std::string("deferredFrameTransformBuffer"), DEFERRED_FRAME_TRANSFORM_BUFFER_SLOT)); @@ -546,9 +551,7 @@ const gpu::PipelinePointer DebugLightClusters::getDrawClusterFromDepthPipeline() auto state = std::make_shared(); - - // state->setDepthTest(true, false, gpu::LESS_EQUAL); - + // Blend on transparent state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA); @@ -560,23 +563,27 @@ const gpu::PipelinePointer DebugLightClusters::getDrawClusterFromDepthPipeline() const gpu::PipelinePointer DebugLightClusters::getDrawClusterContentPipeline() { if (!_drawClusterContent) { - auto vs = gpu::Shader::createVertex(std::string(lightClusters_drawClusterContent_vert)); + // auto vs = gpu::Shader::createVertex(std::string(lightClusters_drawClusterContent_vert)); + auto vs = gpu::StandardShaderLib::getDrawUnitQuadTexcoordVS(); auto ps = gpu::Shader::createPixel(std::string(lightClusters_drawClusterContent_frag)); gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps); gpu::Shader::BindingSet slotBindings; + slotBindings.insert(gpu::Shader::Binding(std::string("lightBuffer"), LIGHT_GPU_SLOT)); + slotBindings.insert(gpu::Shader::Binding(std::string("frustumGridBuffer"), LIGHT_CLUSTER_GRID_FRUSTUM_GRID_SLOT)); slotBindings.insert(gpu::Shader::Binding(std::string("clusterGridBuffer"), LIGHT_CLUSTER_GRID_CLUSTER_GRID_SLOT)); slotBindings.insert(gpu::Shader::Binding(std::string("clusterContentBuffer"), LIGHT_CLUSTER_GRID_CLUSTER_CONTENT_SLOT)); + slotBindings.insert(gpu::Shader::Binding(std::string("linearZeyeMap"), DEFERRED_BUFFER_LINEAR_DEPTH_UNIT)); + slotBindings.insert(gpu::Shader::Binding(std::string("cameraCorrectionBuffer"), CAMERA_CORRECTION_BUFFER_SLOT)); + slotBindings.insert(gpu::Shader::Binding(std::string("deferredFrameTransformBuffer"), DEFERRED_FRAME_TRANSFORM_BUFFER_SLOT)); gpu::Shader::makeProgram(*program, slotBindings); auto state = std::make_shared(); - - state->setDepthTest(true, false, gpu::LESS_EQUAL); - + // Blend on transparent state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA); @@ -611,6 +618,14 @@ void DebugLightClusters::run(const render::SceneContextPointer& sceneContext, co // Then the actual ClusterGrid attributes batch.setModelTransform(Transform()); + + // Bind the G-Buffer surfaces +/* batch.setResourceTexture(DEFERRED_BUFFER_COLOR_UNIT, deferredFramebuffer->getDeferredColorTexture()); + batch.setResourceTexture(DEFERRED_BUFFER_NORMAL_UNIT, deferredFramebuffer->getDeferredNormalTexture()); + batch.setResourceTexture(DEFERRED_BUFFER_EMISSIVE_UNIT, deferredFramebuffer->getDeferredSpecularTexture()); + batch.setResourceTexture(DEFERRED_BUFFER_DEPTH_UNIT, deferredFramebuffer->getPrimaryDepthTexture()); +*/ + batch.setUniformBuffer(LIGHT_GPU_SLOT, lightClusters->_lightStage->_lightArrayBuffer); batch.setUniformBuffer(LIGHT_CLUSTER_GRID_FRUSTUM_GRID_SLOT, lightClusters->_frustumGridBuffer); batch.setUniformBuffer(LIGHT_CLUSTER_GRID_CLUSTER_GRID_SLOT, lightClusters->_clusterGridBuffer); batch.setUniformBuffer(LIGHT_CLUSTER_GRID_CLUSTER_CONTENT_SLOT, lightClusters->_clusterContentBuffer); @@ -626,9 +641,7 @@ void DebugLightClusters::run(const render::SceneContextPointer& sceneContext, co } batch.draw(gpu::TRIANGLE_STRIP, 4, 0); - - // Probably not necessary in the long run because the gpu layer would unbound this texture if used as render target - + batch.setResourceTexture(DEFERRED_BUFFER_LINEAR_DEPTH_UNIT, nullptr); batch.setUniformBuffer(DEFERRED_FRAME_TRANSFORM_BUFFER_SLOT, nullptr); } @@ -637,10 +650,16 @@ void DebugLightClusters::run(const render::SceneContextPointer& sceneContext, co // bind the one gpu::Pipeline we need batch.setPipeline(getDrawClusterContentPipeline()); + batch.setUniformBuffer(DEFERRED_FRAME_TRANSFORM_BUFFER_SLOT, deferredTransform->getFrameTransformBuffer()); - auto dims = lightClusters->_frustumGridBuffer->dims; - glm::ivec3 summedDims(dims.x*dims.y * dims.z, dims.x*dims.y, dims.x); - batch.drawInstanced(summedDims.x, gpu::LINES, 24, 0); + if (linearDepthTarget) { + batch.setResourceTexture(DEFERRED_BUFFER_LINEAR_DEPTH_UNIT, linearDepthTarget->getLinearDepthTexture()); + } + + batch.draw(gpu::TRIANGLE_STRIP, 4, 0); + + batch.setResourceTexture(DEFERRED_BUFFER_LINEAR_DEPTH_UNIT, nullptr); + batch.setUniformBuffer(DEFERRED_FRAME_TRANSFORM_BUFFER_SLOT, nullptr); } if (doDrawGrid) { @@ -651,6 +670,17 @@ void DebugLightClusters::run(const render::SceneContextPointer& sceneContext, co glm::ivec3 summedDims(dims.x*dims.y * dims.z, dims.x*dims.y, dims.x); batch.drawInstanced(summedDims.x, gpu::LINES, 24, 0); } + + batch.setUniformBuffer(LIGHT_GPU_SLOT, nullptr); + batch.setUniformBuffer(LIGHT_CLUSTER_GRID_FRUSTUM_GRID_SLOT, nullptr); + batch.setUniformBuffer(LIGHT_CLUSTER_GRID_CLUSTER_GRID_SLOT, nullptr); + batch.setUniformBuffer(LIGHT_CLUSTER_GRID_CLUSTER_CONTENT_SLOT, nullptr); + + batch.setResourceTexture(DEFERRED_BUFFER_COLOR_UNIT, nullptr); + batch.setResourceTexture(DEFERRED_BUFFER_NORMAL_UNIT, nullptr); + batch.setResourceTexture(DEFERRED_BUFFER_EMISSIVE_UNIT, nullptr); + batch.setResourceTexture(DEFERRED_BUFFER_DEPTH_UNIT, nullptr); + args->_context->appendFrameBatch(batch); } \ No newline at end of file diff --git a/libraries/render-utils/src/lightClusters_drawClusterContent.slf b/libraries/render-utils/src/lightClusters_drawClusterContent.slf index b31479554f..284e7cb9fe 100644 --- a/libraries/render-utils/src/lightClusters_drawClusterContent.slf +++ b/libraries/render-utils/src/lightClusters_drawClusterContent.slf @@ -1,7 +1,7 @@ <@include gpu/Config.slh@> <$VERSION_HEADER$> // Generated on <$_SCRIBE_DATE$> -// lightClusters_drawClusterContent.slf +// lightClusters_drawClusterFro Depth.slf // // Created by Sam Gateau on 9/8/2016. // Copyright 2015 High Fidelity, Inc. @@ -10,10 +10,86 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -in vec4 varColor; -out vec4 outFragColor; +// Everything about deferred buffer +<@include DeferredBufferRead.slh@> + + +<@include model/Light.slh@> +<$declareLightBuffer(128)$> + +<@include LightClusterGrid.slh@> + +<@include gpu/Color.slh@> +<$declareColorWheel()$> + + +in vec2 varTexCoord0; +out vec4 _fragColor; void main(void) { - outFragColor = varColor; + + // Grab the fragment data from the uv + vec2 texCoord = varTexCoord0.st; + + vec4 fragEyePos = unpackDeferredPositionFromZeye(texCoord); + vec4 fragWorldPos = getViewInverse() * fragEyePos; + + // From frag world pos find the cluster + vec4 clusterEyePos = frustumGrid_worldToEye(fragWorldPos); + ivec3 clusterPos = frustumGrid_eyeToClusterPos(clusterEyePos.xyz); + + + ivec3 cluster = clusterGrid_getCluster(frustumGrid_clusterToIndex(clusterPos)); + int numLights = cluster.x + cluster.y; + float numLightsScale = clamp(numLights * 0.05, 0.01, 1.0); + + ivec2 clusterAddress = ivec2(numLights, cluster.z); + + ivec3 dims = frustumGrid.dims.xyz; + dims.z +=1; + ivec3 summedDims = ivec3(dims.x * dims.y, dims.x, 1); + + if (clusterPos.x < 0 || clusterPos.x >= dims.x) { + _fragColor = vec4(0.0); + return; + } + + if (clusterPos.y < 0 || clusterPos.y >= dims.y) { + _fragColor = vec4(0.0); + return; + } + if (clusterPos.z < 0 || clusterPos.z > dims.z) { + _fragColor = vec4(0.0); + return; + } + + int numLightTouching = 0; + for (int i = 0; i < numLights; i++) { + // Need the light now + int theLightIndex = clusterGrid_getClusterLightId(i, clusterAddress); + Light light = getLight(theLightIndex); + + // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space + vec4 fragLightVecLen2; + vec4 fragLightDirLen; + float cosSpotAngle; + + if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragWorldPos.xyz, fragLightVecLen2)) { + continue; + } + // Allright we re in the light sphere volume + fragLightDirLen.w = length(fragLightVecLen2.xyz); + fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w; + + // Check spot + if ((i >= cluster.x) && !lightVolume_clipFragToLightVolumeSpotSide(light.volume, fragLightDirLen, cosSpotAngle)) { + continue; + } + + numLightTouching++; + } + + _fragColor = vec4(colorWheel(numLightTouching/20.0f), (numLightTouching > 0 ? 0.5 + 0.5 * numLightsScale : 0.0)); } + diff --git a/libraries/render-utils/src/local_lights_shading.slf b/libraries/render-utils/src/local_lights_shading.slf index 128d128188..b8e70f439d 100644 --- a/libraries/render-utils/src/local_lights_shading.slf +++ b/libraries/render-utils/src/local_lights_shading.slf @@ -79,9 +79,6 @@ void main(void) { discard; } - - - vec4 midNormalCurvature; vec4 lowNormalCurvature; if (frag.mode == FRAG_MODE_SCATTERING) { From c72b3308211c143731f09ab17b34c7f55638e88b Mon Sep 17 00:00:00 2001 From: samcake Date: Mon, 3 Oct 2016 15:34:54 -0700 Subject: [PATCH 54/75] Simple change to the get cluster interface --- libraries/render-utils/src/LightClusterGrid.slh | 4 ++-- .../render-utils/src/lightClusters_drawClusterContent.slf | 4 ++-- libraries/render-utils/src/local_lights_shading.slf | 5 ++--- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/libraries/render-utils/src/LightClusterGrid.slh b/libraries/render-utils/src/LightClusterGrid.slh index 3eb3b53ccc..efb38f621e 100644 --- a/libraries/render-utils/src/LightClusterGrid.slh +++ b/libraries/render-utils/src/LightClusterGrid.slh @@ -69,8 +69,8 @@ ivec3 clusterGrid_getCluster(int index) { return ivec3(numPointLights, numSpotLights, contentOffset); } -int clusterGrid_getClusterLightId(int index, ivec2 cluster) { - int arrayElement = cluster.y + index; +int clusterGrid_getClusterLightId(int index, int offset) { + int arrayElement = offset + index; int element = _clusterGridContent[arrayElement]; return element; // int element = _clusterGridContent[arrayElement >> 1]; diff --git a/libraries/render-utils/src/lightClusters_drawClusterContent.slf b/libraries/render-utils/src/lightClusters_drawClusterContent.slf index 284e7cb9fe..3c9f7bad1c 100644 --- a/libraries/render-utils/src/lightClusters_drawClusterContent.slf +++ b/libraries/render-utils/src/lightClusters_drawClusterContent.slf @@ -44,7 +44,7 @@ void main(void) { int numLights = cluster.x + cluster.y; float numLightsScale = clamp(numLights * 0.05, 0.01, 1.0); - ivec2 clusterAddress = ivec2(numLights, cluster.z); + int clusterOffset = cluster.z; ivec3 dims = frustumGrid.dims.xyz; dims.z +=1; @@ -67,7 +67,7 @@ void main(void) { int numLightTouching = 0; for (int i = 0; i < numLights; i++) { // Need the light now - int theLightIndex = clusterGrid_getClusterLightId(i, clusterAddress); + int theLightIndex = clusterGrid_getClusterLightId(i, clusterOffset); Light light = getLight(theLightIndex); // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space diff --git a/libraries/render-utils/src/local_lights_shading.slf b/libraries/render-utils/src/local_lights_shading.slf index b8e70f439d..1522239e7f 100644 --- a/libraries/render-utils/src/local_lights_shading.slf +++ b/libraries/render-utils/src/local_lights_shading.slf @@ -65,7 +65,6 @@ void main(void) { discard; } int lightClusterOffset = cluster.z; - ivec2 clusterAddress = ivec2(numLights, lightClusterOffset); ivec3 dims = frustumGrid.dims.xyz; if (clusterPos.x < 0 || clusterPos.x >= dims.x) { @@ -97,7 +96,7 @@ void main(void) { int numLightTouching = 0; for (int i = 0; i < cluster.x; i++) { // Need the light now - int theLightIndex = clusterGrid_getClusterLightId(i, clusterAddress); + int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset); Light light = getLight(theLightIndex); // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space @@ -145,7 +144,7 @@ void main(void) { for (int i = cluster.x; i < numLights; i++) { // Need the light now - int theLightIndex = clusterGrid_getClusterLightId(i, clusterAddress); + int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset); Light light = getLight(theLightIndex); // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space From a378a6eccb8105227595ebc3a8ff7aa51840f810 Mon Sep 17 00:00:00 2001 From: samcake Date: Mon, 3 Oct 2016 18:28:44 -0700 Subject: [PATCH 55/75] separate the rendering of the light outline from the main rendering and introduce a way to support both platform --- .../src/DeferredLightingEffect.cpp | 11 ++ .../render-utils/src/DeferredLightingEffect.h | 2 + .../render-utils/src/LightClusterGrid.slh | 19 ++- libraries/render-utils/src/LightPoint.slh | 21 +++ libraries/render-utils/src/LightSpot.slh | 22 +++ libraries/render-utils/src/LightingModel.h | 3 +- .../src/local_lights_drawOutline.slf | 153 ++++++++++++++++++ 7 files changed, 221 insertions(+), 10 deletions(-) create mode 100644 libraries/render-utils/src/local_lights_drawOutline.slf diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index ace969563e..084ec0e746 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -36,6 +36,7 @@ #include "directional_skybox_light_shadow_frag.h" #include "local_lights_shading_frag.h" +#include "local_lights_drawOutline_frag.h" #include "point_light_frag.h" #include "spot_light_frag.h" @@ -103,6 +104,7 @@ void DeferredLightingEffect::init() { _directionalSkyboxLightShadowLocations = std::make_shared(); _localLightLocations = std::make_shared(); + _localLightOutlineLocations = std::make_shared(); _pointLightLocations = std::make_shared(); _spotLightLocations = std::make_shared(); @@ -115,6 +117,7 @@ void DeferredLightingEffect::init() { loadLightProgram(deferred_light_vert, directional_skybox_light_shadow_frag, false, _directionalSkyboxLightShadow, _directionalSkyboxLightShadowLocations); loadLightProgram(deferred_light_vert, local_lights_shading_frag, true, _localLight, _localLightLocations); + loadLightProgram(deferred_light_vert, local_lights_drawOutline_frag, true, _localLightOutline, _localLightOutlineLocations); loadLightVolumeProgram(deferred_light_point_vert, no_light_frag, false, _pointLightBack, _pointLightLocations); loadLightVolumeProgram(deferred_light_point_vert, no_light_frag, true, _pointLightFront, _pointLightLocations); @@ -795,6 +798,14 @@ void RenderDeferredLocals::run(const render::SceneContextPointer& sceneContext, batch._glUniform4fv(deferredLightingEffect->_localLightLocations->texcoordFrameTransform, 1, reinterpret_cast(&textureFrameTransform)); batch.draw(gpu::TRIANGLE_STRIP, 4); + + // Draw outline as well ? + if (lightingModel->isShowLightContourEnabled()) { + batch.setPipeline(deferredLightingEffect->_localLightOutline); + batch._glUniform4fv(deferredLightingEffect->_localLightOutlineLocations->texcoordFrameTransform, 1, reinterpret_cast(&textureFrameTransform)); + + batch.draw(gpu::TRIANGLE_STRIP, 4); + } } } } diff --git a/libraries/render-utils/src/DeferredLightingEffect.h b/libraries/render-utils/src/DeferredLightingEffect.h index 9462dbcc4e..d2b8dd42b2 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.h +++ b/libraries/render-utils/src/DeferredLightingEffect.h @@ -90,6 +90,7 @@ private: gpu::PipelinePointer _directionalLightShadow; gpu::PipelinePointer _localLight; + gpu::PipelinePointer _localLightOutline; gpu::PipelinePointer _pointLightBack; gpu::PipelinePointer _pointLightFront; @@ -105,6 +106,7 @@ private: LightLocationsPtr _directionalLightShadowLocations; LightLocationsPtr _localLightLocations; + LightLocationsPtr _localLightOutlineLocations; LightLocationsPtr _pointLightLocations; LightLocationsPtr _spotLightLocations; diff --git a/libraries/render-utils/src/LightClusterGrid.slh b/libraries/render-utils/src/LightClusterGrid.slh index efb38f621e..80203ef49b 100644 --- a/libraries/render-utils/src/LightClusterGrid.slh +++ b/libraries/render-utils/src/LightClusterGrid.slh @@ -49,20 +49,24 @@ float projection_getFar(mat4 projection) { <@if GLPROFILE == MAC_GL @> #define GRID_NUM_ELEMENTS 4096 +#define GRID_INDEX_TYPE ivec4 +#define GRID_FETCH_BUFFER(i) i / 4][i % 4 <@else@> #define GRID_NUM_ELEMENTS 16384 +#define GRID_INDEX_TYPE int +#define GRID_FETCH_BUFFER(i) i <@endif@> uniform clusterGridBuffer { - int _clusterGridTable[GRID_NUM_ELEMENTS]; + GRID_INDEX_TYPE _clusterGridTable[GRID_NUM_ELEMENTS]; }; uniform clusterContentBuffer { - int _clusterGridContent[GRID_NUM_ELEMENTS]; + GRID_INDEX_TYPE _clusterGridContent[GRID_NUM_ELEMENTS]; }; ivec3 clusterGrid_getCluster(int index) { - int clusterDesc = _clusterGridTable[index]; + int clusterDesc = _clusterGridTable[GRID_FETCH_BUFFER(index)]; int numPointLights = 0xFF & (clusterDesc >> 16); int numSpotLights = 0xFF & (clusterDesc >> 24); int contentOffset = 0xFFFF & (clusterDesc); @@ -70,12 +74,11 @@ ivec3 clusterGrid_getCluster(int index) { } int clusterGrid_getClusterLightId(int index, int offset) { - int arrayElement = offset + index; - int element = _clusterGridContent[arrayElement]; + int elementIndex = offset + index; + int element = _clusterGridContent[GRID_FETCH_BUFFER(elementIndex)]; return element; -// int element = _clusterGridContent[arrayElement >> 1]; - -// return (((arrayElement & 0x00000001) == 1) ? (element >> 16) : element) & 0x0000FFFF; + //int element = _clusterGridContent[GRID_FETCH_BUFFER(elementIndex)]; + // return (((elementIndex & 0x00000001) == 1) ? (element >> 16) : element) & 0x0000FFFF; } <@endif@> diff --git a/libraries/render-utils/src/LightPoint.slh b/libraries/render-utils/src/LightPoint.slh index 5160396e8a..431731ec18 100644 --- a/libraries/render-utils/src/LightPoint.slh +++ b/libraries/render-utils/src/LightPoint.slh @@ -50,3 +50,24 @@ void evalLightingPoint(out vec3 diffuse, out vec3 specular, Light light, <@endfunc@> +<@func declareDrawPointOutline()@> + +bool evalLightPointEdge(out vec3 color, Light light, vec4 fragLightDirLen, vec3 fragEyeDir) { + // Allright we re valid in the volume + float fragLightDistance = fragLightDirLen.w; + vec3 fragLightDir = fragLightDirLen.xyz; + + // Show edges + float edge = abs(2.0 * ((lightVolume_getRadius(light.volume) - fragLightDistance) / (0.1)) - 1.0); + if (edge < 1) { + float edgeCoord = exp2(-8.0*edge*edge); + color = vec3(edgeCoord * edgeCoord * getLightColor(light)); + } + + return (edge < 1); +} + +<@endfunc@> + + + diff --git a/libraries/render-utils/src/LightSpot.slh b/libraries/render-utils/src/LightSpot.slh index a3be944494..6ce21f8823 100644 --- a/libraries/render-utils/src/LightSpot.slh +++ b/libraries/render-utils/src/LightSpot.slh @@ -54,4 +54,26 @@ void evalLightingSpot(out vec3 diffuse, out vec3 specular, Light light, <@endfunc@> +<@func declareDrawSpotOutline()@> + +bool evalLightSpotEdge(out vec3 color, Light light, vec4 fragLightDirLen, float cosSpotAngle, vec3 fragEyeDir) { + // Allright we re valid in the volume + float fragLightDistance = fragLightDirLen.w; + vec3 fragLightDir = fragLightDirLen.xyz; + + // Show edges + float edgeDistR = (lightVolume_getRadius(light.volume) - fragLightDistance); + float edgeDistS = dot(fragLightDistance * vec2(cosSpotAngle, sqrt(1.0 - cosSpotAngle * cosSpotAngle)), -lightVolume_getSpotOutsideNormal2(light.volume)); + float edgeDist = min(edgeDistR, edgeDistS); + float edge = abs(2.0 * (edgeDist / (0.1)) - 1.0); + if (edge < 1) { + float edgeCoord = exp2(-8.0*edge*edge); + color = vec3(edgeCoord * edgeCoord * getLightColor(light)); + } + + return (edge < 1); +} + +<@endfunc@> + diff --git a/libraries/render-utils/src/LightingModel.h b/libraries/render-utils/src/LightingModel.h index 5bb0e621a4..8f3ee9b7d6 100644 --- a/libraries/render-utils/src/LightingModel.h +++ b/libraries/render-utils/src/LightingModel.h @@ -143,8 +143,7 @@ public: bool enablePointLight{ true }; bool enableSpotLight{ true }; - // bool showLightContour { false }; // false by default - bool showLightContour { true }; // false by default + bool showLightContour { false }; // false by default signals: void dirty(); diff --git a/libraries/render-utils/src/local_lights_drawOutline.slf b/libraries/render-utils/src/local_lights_drawOutline.slf new file mode 100644 index 0000000000..3aa210a241 --- /dev/null +++ b/libraries/render-utils/src/local_lights_drawOutline.slf @@ -0,0 +1,153 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// local_lights_drawOutline.frag +// fragment shader +// +// Created by Sam Gateau on 9/6/2016. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +// Everything about deferred buffer +<@include DeferredBufferRead.slh@> + +<$declareDeferredCurvature()$> + +// Everything about light +<@include model/Light.slh@> +<$declareLightBuffer(128)$> +<@include LightingModel.slh@> + + +<@include LightPoint.slh@> +<$declareDrawPointOutline()$> +<@include LightSpot.slh@> +<$declareDrawSpotOutline()$> + +<@include LightClusterGrid.slh@> + + + +in vec2 _texCoord0; +out vec4 _fragColor; + +void main(void) { + + // Grab the fragment data from the uv + vec2 texCoord = _texCoord0.st; + + vec4 fragPosition = unpackDeferredPositionFromZeye(texCoord); + DeferredFragment frag = unpackDeferredFragmentNoPosition(texCoord); + + if (frag.mode == FRAG_MODE_UNLIT) { + discard; + } + + frag.position = fragPosition; + + + // Frag pos in world + mat4 invViewMat = getViewInverse(); + vec4 fragPos = invViewMat * fragPosition; + + // From frag world pos find the cluster + vec4 clusterEyePos = frustumGrid_worldToEye(fragPos); + ivec3 clusterPos = frustumGrid_eyeToClusterPos(clusterEyePos.xyz); + + ivec3 cluster = clusterGrid_getCluster(frustumGrid_clusterToIndex(clusterPos)); + int numLights = cluster.x + cluster.y; + if (numLights <= 0) { + discard; + } + int lightClusterOffset = cluster.z; + + ivec3 dims = frustumGrid.dims.xyz; + if (clusterPos.x < 0 || clusterPos.x >= dims.x) { + discard; + } + + if (clusterPos.y < 0 || clusterPos.y >= dims.y) { + discard; + } + if (clusterPos.z < 0 || clusterPos.z > dims.z) { + discard; + } + + // Frag to eye vec + vec4 fragEyeVector = invViewMat * vec4(-frag.position.xyz, 0.0); + vec3 fragEyeDir = normalize(fragEyeVector.xyz); + + int numLightTouching = 0; + for (int i = 0; i < cluster.x; i++) { + // Need the light now + int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset); + Light light = getLight(theLightIndex); + + // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space + vec4 fragLightVecLen2; + vec4 fragLightDirLen; + + if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragPos.xyz, fragLightVecLen2)) { + continue; + } + + // Allright we re in the light sphere volume + fragLightDirLen.w = length(fragLightVecLen2.xyz); + fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w; + if (dot(frag.normal, fragLightDirLen.xyz) < 0.0) { + continue; + } + + numLightTouching++; + + // Allright we re valid in the volume + float fragLightDistance = fragLightDirLen.w; + vec3 fragLightDir = fragLightDirLen.xyz; + + vec3 color = vec3(0.0); + if (evalLightPointEdge(color, light, fragLightDirLen, fragEyeDir)) { + _fragColor.rgb += color; + } + } + + for (int i = cluster.x; i < numLights; i++) { + // Need the light now + int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset); + Light light = getLight(theLightIndex); + + // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space + vec4 fragLightVecLen2; + vec4 fragLightDirLen; + float cosSpotAngle; + + if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragPos.xyz, fragLightVecLen2)) { + continue; + } + + // Allright we re in the light sphere volume + fragLightDirLen.w = length(fragLightVecLen2.xyz); + fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w; + if (dot(frag.normal, fragLightDirLen.xyz) < 0.0) { + continue; + } + + // Check spot + if (!lightVolume_clipFragToLightVolumeSpotSide(light.volume, fragLightDirLen, cosSpotAngle)) { + continue; + } + + numLightTouching++; + + vec3 color = vec3(0.0); + + if (evalLightSpotEdge(color, light, fragLightDirLen, cosSpotAngle, fragEyeDir)) { + _fragColor.rgb += color; + } + } + +} + From 6aa39ec95a840fa03e6b82cd2a100ec9da4cd7ec Mon Sep 17 00:00:00 2001 From: samcake Date: Tue, 4 Oct 2016 11:03:12 -0700 Subject: [PATCH 56/75] Polish the debugging of the light volumes --- libraries/gpu/src/gpu/Color.slh | 19 +++++++++ libraries/render-utils/src/LightClusters.cpp | 42 ++++++++++++------- .../src/lightClusters_drawClusterContent.slf | 2 +- 3 files changed, 46 insertions(+), 17 deletions(-) diff --git a/libraries/gpu/src/gpu/Color.slh b/libraries/gpu/src/gpu/Color.slh index 4330b34b90..526cc3dd46 100644 --- a/libraries/gpu/src/gpu/Color.slh +++ b/libraries/gpu/src/gpu/Color.slh @@ -46,6 +46,25 @@ vec3 colorWheel(float normalizedHue) { return vec3(1.f, 0.f, 0.f); } } + +vec3 colorRamp(float normalizedHue) { + float v = normalizedHue * 5.f; + if (v < 0.f) { + return vec3(1.f, 0.f, 0.f); + } else if (v < 1.f) { + return vec3(1.f, v, 0.f); + } else if (v < 2.f) { + return vec3(1.f - (v - 1.f), 1.f, 0.f); + } else if (v < 3.f) { + return vec3(0.f, 1.f, (v - 2.f)); + } else if (v < 4.f) { + return vec3(0.f, 1.f - (v - 3.f), 1.f); + } else if (v < 5.f) { + return vec3((v - 4.f), 0.f, 1.f); + } else { + return vec3(1.f, 0.f, 1.f); + } +} <@endfunc@> <@endif@> \ No newline at end of file diff --git a/libraries/render-utils/src/LightClusters.cpp b/libraries/render-utils/src/LightClusters.cpp index 2eda0f95a2..b7ab88f119 100644 --- a/libraries/render-utils/src/LightClusters.cpp +++ b/libraries/render-utils/src/LightClusters.cpp @@ -429,7 +429,6 @@ void LightClusters::updateClusters() { } } - // _clusterGrid[i] = (uint32_t)((numLights << 16) | offset); _clusterGrid[i] = (uint32_t)((0xFF000000 & (numLightsSpot << 24)) | (0x00FF0000 & (numLightsPoint << 16)) | (0x0000FFFF & offset)); @@ -595,16 +594,23 @@ const gpu::PipelinePointer DebugLightClusters::getDrawClusterContentPipeline() { void DebugLightClusters::run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext, const Inputs& inputs) { + if (!(doDrawClusterFromDepth || doDrawContent || doDrawGrid)) { + return; + } + auto deferredTransform = inputs.get0(); auto deferredFramebuffer = inputs.get1(); auto lightingModel = inputs.get2(); auto linearDepthTarget = inputs.get3(); auto lightClusters = inputs.get4(); - + auto args = renderContext->args; - + gpu::Batch batch; + batch.enableStereo(false); + + // Assign the camera transform batch.setViewportTransform(args->_viewport); glm::mat4 projMat; @@ -661,26 +667,30 @@ void DebugLightClusters::run(const render::SceneContextPointer& sceneContext, co batch.setResourceTexture(DEFERRED_BUFFER_LINEAR_DEPTH_UNIT, nullptr); batch.setUniformBuffer(DEFERRED_FRAME_TRANSFORM_BUFFER_SLOT, nullptr); } - + + + + gpu::Batch drawGridAndCleanBatch; + if (doDrawGrid) { // bind the one gpu::Pipeline we need - batch.setPipeline(getDrawClusterGridPipeline()); - + drawGridAndCleanBatch.setPipeline(getDrawClusterGridPipeline()); + auto dims = lightClusters->_frustumGridBuffer->dims; glm::ivec3 summedDims(dims.x*dims.y * dims.z, dims.x*dims.y, dims.x); - batch.drawInstanced(summedDims.x, gpu::LINES, 24, 0); + drawGridAndCleanBatch.drawInstanced(summedDims.x, gpu::LINES, 24, 0); } - batch.setUniformBuffer(LIGHT_GPU_SLOT, nullptr); - batch.setUniformBuffer(LIGHT_CLUSTER_GRID_FRUSTUM_GRID_SLOT, nullptr); - batch.setUniformBuffer(LIGHT_CLUSTER_GRID_CLUSTER_GRID_SLOT, nullptr); - batch.setUniformBuffer(LIGHT_CLUSTER_GRID_CLUSTER_CONTENT_SLOT, nullptr); + drawGridAndCleanBatch.setUniformBuffer(LIGHT_GPU_SLOT, nullptr); + drawGridAndCleanBatch.setUniformBuffer(LIGHT_CLUSTER_GRID_FRUSTUM_GRID_SLOT, nullptr); + drawGridAndCleanBatch.setUniformBuffer(LIGHT_CLUSTER_GRID_CLUSTER_GRID_SLOT, nullptr); + drawGridAndCleanBatch.setUniformBuffer(LIGHT_CLUSTER_GRID_CLUSTER_CONTENT_SLOT, nullptr); - batch.setResourceTexture(DEFERRED_BUFFER_COLOR_UNIT, nullptr); - batch.setResourceTexture(DEFERRED_BUFFER_NORMAL_UNIT, nullptr); - batch.setResourceTexture(DEFERRED_BUFFER_EMISSIVE_UNIT, nullptr); - batch.setResourceTexture(DEFERRED_BUFFER_DEPTH_UNIT, nullptr); + drawGridAndCleanBatch.setResourceTexture(DEFERRED_BUFFER_COLOR_UNIT, nullptr); + drawGridAndCleanBatch.setResourceTexture(DEFERRED_BUFFER_NORMAL_UNIT, nullptr); + drawGridAndCleanBatch.setResourceTexture(DEFERRED_BUFFER_EMISSIVE_UNIT, nullptr); + drawGridAndCleanBatch.setResourceTexture(DEFERRED_BUFFER_DEPTH_UNIT, nullptr); args->_context->appendFrameBatch(batch); - + args->_context->appendFrameBatch(drawGridAndCleanBatch); } \ No newline at end of file diff --git a/libraries/render-utils/src/lightClusters_drawClusterContent.slf b/libraries/render-utils/src/lightClusters_drawClusterContent.slf index 3c9f7bad1c..fe8d850e8a 100644 --- a/libraries/render-utils/src/lightClusters_drawClusterContent.slf +++ b/libraries/render-utils/src/lightClusters_drawClusterContent.slf @@ -90,6 +90,6 @@ void main(void) { numLightTouching++; } - _fragColor = vec4(colorWheel(numLightTouching/20.0f), (numLightTouching > 0 ? 0.5 + 0.5 * numLightsScale : 0.0)); + _fragColor = vec4(colorRamp(1.0 - (numLightTouching / 12.0f)), (numLightTouching > 0 ? 0.5 + 0.5 * numLightsScale : 0.0)); } From 1c2a6722149ea66b50543041fe1488e2670d5fb8 Mon Sep 17 00:00:00 2001 From: samcake Date: Tue, 4 Oct 2016 13:29:08 -0700 Subject: [PATCH 57/75] Adjust the grid size for mac --- libraries/render-utils/src/LightClusters.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/render-utils/src/LightClusters.cpp b/libraries/render-utils/src/LightClusters.cpp index b7ab88f119..6d6ea005d5 100644 --- a/libraries/render-utils/src/LightClusters.cpp +++ b/libraries/render-utils/src/LightClusters.cpp @@ -74,7 +74,7 @@ void FrustumGrid::generateGridPlanes(Planes& xPlanes, Planes& yPlanes, Planes& z #include "DeferredLightingEffect.h" #ifdef Q_OS_MAC -const glm::uvec4 LightClusters::MAX_GRID_DIMENSIONS { 8, 8, 8, 4096 }; +const glm::uvec4 LightClusters::MAX_GRID_DIMENSIONS { 16, 16, 16, 16384 }; #else const glm::uvec4 LightClusters::MAX_GRID_DIMENSIONS { 32, 32, 31, 16384 }; #endif From 3e11eb41296cee3913348a77f9a01d4a7c2d14b5 Mon Sep 17 00:00:00 2001 From: samcake Date: Tue, 4 Oct 2016 13:55:53 -0700 Subject: [PATCH 58/75] Try avoiding the basd update of the buffer for the grid content --- libraries/render-utils/src/LightClusters.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libraries/render-utils/src/LightClusters.cpp b/libraries/render-utils/src/LightClusters.cpp index 6d6ea005d5..d3c7e40d48 100644 --- a/libraries/render-utils/src/LightClusters.cpp +++ b/libraries/render-utils/src/LightClusters.cpp @@ -444,7 +444,10 @@ void LightClusters::updateClusters() { // update the buffers _clusterGridBuffer._buffer->setData(_clusterGridBuffer._size, (gpu::Byte*) _clusterGrid.data()); - _clusterContentBuffer._buffer->setSubData(0, indexOffset * sizeof(LightIndex), (gpu::Byte*) _clusterContent.data()); + //_clusterGridBuffer._buffer->setSubData(0, _clusterGridBuffer._size, (gpu::Byte*) _clusterGrid.data()); + _clusterContentBuffer._buffer->setData(indexOffset * sizeof(LightIndex), (gpu::Byte*) _clusterContent.data()); + + // _clusterContentBuffer._buffer->setSubData(0, indexOffset * sizeof(LightIndex), (gpu::Byte*) _clusterContent.data()); } From 8c561eaa44b47dcdacc7461e94c3f4dcc082099d Mon Sep 17 00:00:00 2001 From: samcake Date: Tue, 4 Oct 2016 18:19:42 -0700 Subject: [PATCH 59/75] trying to whipe these buffer cleans but doesn;t seems to make a different in release, it is working clena in debug ... keep on looking --- .../render-utils/src/LightClusterGrid.slh | 1 - libraries/render-utils/src/LightClusters.cpp | 20 +++++++++++-------- .../render-utils/src/local_lights_shading.slf | 1 - 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/libraries/render-utils/src/LightClusterGrid.slh b/libraries/render-utils/src/LightClusterGrid.slh index 80203ef49b..24d4a8fbc8 100644 --- a/libraries/render-utils/src/LightClusterGrid.slh +++ b/libraries/render-utils/src/LightClusterGrid.slh @@ -46,7 +46,6 @@ float projection_getFar(mat4 projection) { // end of hybrid include - <@if GLPROFILE == MAC_GL @> #define GRID_NUM_ELEMENTS 4096 #define GRID_INDEX_TYPE ivec4 diff --git a/libraries/render-utils/src/LightClusters.cpp b/libraries/render-utils/src/LightClusters.cpp index d3c7e40d48..a29357f493 100644 --- a/libraries/render-utils/src/LightClusters.cpp +++ b/libraries/render-utils/src/LightClusters.cpp @@ -82,8 +82,8 @@ const glm::uvec4 LightClusters::MAX_GRID_DIMENSIONS { 32, 32, 31, 16384 }; LightClusters::LightClusters() : _lightIndicesBuffer(std::make_shared()), - _clusterGridBuffer(std::make_shared(), gpu::Element::INDEX_INT32), - _clusterContentBuffer(std::make_shared(), gpu::Element::INDEX_INT32) { + _clusterGridBuffer(/*std::make_shared(), */gpu::Element::INDEX_INT32), + _clusterContentBuffer(/*std::make_shared(), */gpu::Element::INDEX_INT32) { auto dims = _frustumGridBuffer.edit().dims; _frustumGridBuffer.edit().dims = ivec3(0); // make sure we go through the full reset of the dimensionts ion the setDImensions call setDimensions(dims, MAX_GRID_DIMENSIONS.w); @@ -113,14 +113,19 @@ void LightClusters::setDimensions(glm::uvec3 gridDims, uint32_t listBudget) { _numClusters = numClusters; _clusterGrid.clear(); _clusterGrid.resize(_numClusters, EMPTY_CLUSTER); - _clusterGridBuffer._size = _clusterGridBuffer._buffer->resize(_numClusters * sizeof(uint32_t)); + // _clusterGridBuffer._size = _clusterGridBuffer._buffer->resize(_numClusters * sizeof(uint32_t)); + _clusterGridBuffer._size = (_numClusters * sizeof(uint32_t)); + _clusterGridBuffer._buffer = std::make_shared(_clusterGridBuffer._size, (gpu::Byte*) _clusterGrid.data()/*, _clusterGridBuffer._size*/); } auto configListBudget = std::min(MAX_GRID_DIMENSIONS.w, listBudget); if (configListBudget != _clusterContentBuffer.getNumElements()) { _clusterContent.clear(); _clusterContent.resize(configListBudget, INVALID_LIGHT); - _clusterContentBuffer._size = _clusterContentBuffer._buffer->resize(configListBudget * sizeof(LightIndex)); + // _clusterContentBuffer._size = _clusterContentBuffer._buffer->resize(configListBudget * sizeof(LightIndex)); + _clusterContentBuffer._size = (configListBudget * sizeof(LightIndex)); + // _clusterContentBuffer._buffer->setData(_clusterContentBuffer._size, (gpu::Byte*) _clusterContent.data()); + _clusterContentBuffer._buffer = std::make_shared(_clusterContentBuffer._size, (gpu::Byte*) _clusterContent.data()/*, _clusterContentBuffer._size*/); } } @@ -287,8 +292,10 @@ void LightClusters::updateClusters() { std::vector< std::vector< LightIndex > > clusterGridPoint(_numClusters); std::vector< std::vector< LightIndex > > clusterGridSpot(_numClusters); + _clusterGrid.clear(); _clusterGrid.resize(_numClusters, EMPTY_CLUSTER); uint32_t maxNumIndices = (uint32_t) _clusterContent.size(); + _clusterContent.clear(); _clusterContent.resize(maxNumIndices, INVALID_LIGHT); auto theFrustumGrid(_frustumGridBuffer.get()); @@ -444,10 +451,7 @@ void LightClusters::updateClusters() { // update the buffers _clusterGridBuffer._buffer->setData(_clusterGridBuffer._size, (gpu::Byte*) _clusterGrid.data()); - //_clusterGridBuffer._buffer->setSubData(0, _clusterGridBuffer._size, (gpu::Byte*) _clusterGrid.data()); - _clusterContentBuffer._buffer->setData(indexOffset * sizeof(LightIndex), (gpu::Byte*) _clusterContent.data()); - - // _clusterContentBuffer._buffer->setSubData(0, indexOffset * sizeof(LightIndex), (gpu::Byte*) _clusterContent.data()); + _clusterContentBuffer._buffer->setSubData(0, indexOffset * sizeof(LightIndex), (gpu::Byte*) _clusterContent.data()); } diff --git a/libraries/render-utils/src/local_lights_shading.slf b/libraries/render-utils/src/local_lights_shading.slf index 1522239e7f..c7d49de979 100644 --- a/libraries/render-utils/src/local_lights_shading.slf +++ b/libraries/render-utils/src/local_lights_shading.slf @@ -31,7 +31,6 @@ <@include LightClusterGrid.slh@> - in vec2 _texCoord0; out vec4 _fragColor; From ba88db1b14d3e3a72637304c5b65ff535f8d0a9c Mon Sep 17 00:00:00 2001 From: samcake Date: Wed, 5 Oct 2016 18:28:19 -0700 Subject: [PATCH 60/75] Tried many different things to narrow down the issue of the corrupted memory, it seems to be linked to the grid dimendsions somehow, i m now forcing to reassign the frustum grid dimension on the 10th iteration which seems to fix the issue.... --- libraries/gpu/src/gpu/Buffer.cpp | 3 ++- .../render-utils/src/LightClusterGrid.slh | 6 +++-- libraries/render-utils/src/LightClusters.cpp | 26 ++++++++++++++----- libraries/render-utils/src/LightClusters.h | 24 +++++++++++------ libraries/render-utils/src/LightStage.cpp | 2 +- .../render-utils/src/deferred_light_point.slv | 4 +-- .../render-utils/src/deferred_light_spot.slv | 4 +-- .../src/lightClusters_drawClusterContent.slf | 2 +- .../render-utils/src/local_lights_shading.slf | 2 +- libraries/render-utils/src/spot_light.slf | 4 +-- .../utilities/render/lightClustering.qml | 3 +++ 11 files changed, 53 insertions(+), 27 deletions(-) diff --git a/libraries/gpu/src/gpu/Buffer.cpp b/libraries/gpu/src/gpu/Buffer.cpp index f4cd9e41ba..fb60e0e737 100644 --- a/libraries/gpu/src/gpu/Buffer.cpp +++ b/libraries/gpu/src/gpu/Buffer.cpp @@ -42,7 +42,8 @@ Buffer::Size Buffer::getBufferGPUMemoryUsage() { } Buffer::Buffer(Size pageSize) : - _pages(pageSize) { + _pages(pageSize), + _renderPages(pageSize) { _bufferCPUCount++; } diff --git a/libraries/render-utils/src/LightClusterGrid.slh b/libraries/render-utils/src/LightClusterGrid.slh index 24d4a8fbc8..3cd3bec473 100644 --- a/libraries/render-utils/src/LightClusterGrid.slh +++ b/libraries/render-utils/src/LightClusterGrid.slh @@ -74,10 +74,12 @@ ivec3 clusterGrid_getCluster(int index) { int clusterGrid_getClusterLightId(int index, int offset) { int elementIndex = offset + index; + /* int element = _clusterGridContent[GRID_FETCH_BUFFER(elementIndex)]; return element; - //int element = _clusterGridContent[GRID_FETCH_BUFFER(elementIndex)]; - // return (((elementIndex & 0x00000001) == 1) ? (element >> 16) : element) & 0x0000FFFF; + */ + int element = _clusterGridContent[GRID_FETCH_BUFFER((elementIndex >> 1))]; + return (((elementIndex & 0x00000001) == 1) ? (element >> 16) : element) & 0x0000FFFF; } <@endif@> diff --git a/libraries/render-utils/src/LightClusters.cpp b/libraries/render-utils/src/LightClusters.cpp index a29357f493..98615a72ff 100644 --- a/libraries/render-utils/src/LightClusters.cpp +++ b/libraries/render-utils/src/LightClusters.cpp @@ -101,9 +101,10 @@ void LightClusters::setDimensions(glm::uvec3 gridDims, uint32_t listBudget) { configDimensions.z = std::min(maxNumSlices, configDimensions.z); - + static int numFrames = 0; + numFrames++; auto& dims = _frustumGridBuffer->dims; - if ((dims.x != configDimensions.x) || (dims.y != configDimensions.y) || (dims.z != configDimensions.z)) { + if ((numFrames == 10) || (dims.x != configDimensions.x) || (dims.y != configDimensions.y) || (dims.z != configDimensions.z)) { _frustumGridBuffer.edit().dims = configDimensions; _frustumGridBuffer.edit().generateGridPlanes(_gridPlanes[0], _gridPlanes[1], _gridPlanes[2]); } @@ -115,17 +116,23 @@ void LightClusters::setDimensions(glm::uvec3 gridDims, uint32_t listBudget) { _clusterGrid.resize(_numClusters, EMPTY_CLUSTER); // _clusterGridBuffer._size = _clusterGridBuffer._buffer->resize(_numClusters * sizeof(uint32_t)); _clusterGridBuffer._size = (_numClusters * sizeof(uint32_t)); - _clusterGridBuffer._buffer = std::make_shared(_clusterGridBuffer._size, (gpu::Byte*) _clusterGrid.data()/*, _clusterGridBuffer._size*/); + _clusterGridBuffer._buffer = std::make_shared(_clusterGridBuffer._size, (gpu::Byte*) _clusterGrid.data(), _clusterGridBuffer._size); } auto configListBudget = std::min(MAX_GRID_DIMENSIONS.w, listBudget); - if (configListBudget != _clusterContentBuffer.getNumElements()) { + + // SInce LightINdex is 2bytes, we can fit 2 in a uint32 + if (sizeof(LightIndex) == 2) { + configListBudget *= 2; + } + + if (configListBudget != _clusterContent.size()) { _clusterContent.clear(); _clusterContent.resize(configListBudget, INVALID_LIGHT); // _clusterContentBuffer._size = _clusterContentBuffer._buffer->resize(configListBudget * sizeof(LightIndex)); _clusterContentBuffer._size = (configListBudget * sizeof(LightIndex)); // _clusterContentBuffer._buffer->setData(_clusterContentBuffer._size, (gpu::Byte*) _clusterContent.data()); - _clusterContentBuffer._buffer = std::make_shared(_clusterContentBuffer._size, (gpu::Byte*) _clusterContent.data()/*, _clusterContentBuffer._size*/); + _clusterContentBuffer._buffer = std::make_shared(_clusterContentBuffer._size, (gpu::Byte*) _clusterContent.data(), _clusterContentBuffer._size); } } @@ -287,7 +294,7 @@ uint32_t scanLightVolumeSphere(FrustumGrid& grid, const FrustumGrid::Planes plan return numClustersTouched; } -void LightClusters::updateClusters() { +uint32_t LightClusters::updateClusters() { // Clean up last info std::vector< std::vector< LightIndex > > clusterGridPoint(_numClusters); std::vector< std::vector< LightIndex > > clusterGridSpot(_numClusters); @@ -452,6 +459,8 @@ void LightClusters::updateClusters() { // update the buffers _clusterGridBuffer._buffer->setData(_clusterGridBuffer._size, (gpu::Byte*) _clusterGrid.data()); _clusterContentBuffer._buffer->setSubData(0, indexOffset * sizeof(LightIndex), (gpu::Byte*) _clusterContent.data()); + + return numClusterTouched; } @@ -492,9 +501,12 @@ void LightClusteringPass::run(const render::SceneContextPointer& sceneContext, c _lightClusters->updateLightStage(lightStage); _lightClusters->updateLightFrame(lightStage->_currentFrame, lightingModel->isPointLightEnabled(), lightingModel->isSpotLightEnabled()); - _lightClusters->updateClusters(); + auto numClusterdLights = _lightClusters->updateClusters(); output = _lightClusters; + + auto config = std::static_pointer_cast(renderContext->jobConfig); + config->setNumClusteredLights(numClusterdLights); } DebugLightClusters::DebugLightClusters() { diff --git a/libraries/render-utils/src/LightClusters.h b/libraries/render-utils/src/LightClusters.h index 5c52d44ff1..e01d6c42f7 100644 --- a/libraries/render-utils/src/LightClusters.h +++ b/libraries/render-utils/src/LightClusters.h @@ -24,7 +24,8 @@ public: float rangeFar { 200.0f }; float frustumFar { 10000.0f }; - glm::ivec3 dims { 16, 12, 16 }; + // glm::ivec3 dims { 16, 16, 16 }; + glm::ivec3 dims { 16, 16, 16 }; float spare; glm::mat4 eyeToGridProj; @@ -74,7 +75,7 @@ public: void updateLightFrame(const LightStage::Frame& lightFrame, bool points = true, bool spots = true); - void updateClusters(); + uint32_t updateClusters(); ViewFrustum _frustum; @@ -94,15 +95,12 @@ public: const uint32_t EMPTY_CLUSTER { 0x0000FFFF }; const LightID INVALID_LIGHT { LightStage::INVALID_INDEX }; - using LightIndex = uint32_t; + using LightIndex = uint16_t; std::vector _clusterGrid; std::vector _clusterContent; gpu::BufferView _clusterGridBuffer; gpu::BufferView _clusterContentBuffer; - - - }; using LightClustersPointer = std::shared_ptr; @@ -119,17 +117,26 @@ class LightClusteringPassConfig : public render::Job::Config { Q_PROPERTY(int dimZ MEMBER dimZ NOTIFY dirty) Q_PROPERTY(bool freeze MEMBER freeze NOTIFY dirty) + + Q_PROPERTY(int numClusteredLights MEMBER numClusteredLights NOTIFY dirty) public: LightClusteringPassConfig() : render::Job::Config(true){} float rangeNear{ 0.1f }; float rangeFar{ 200.0f }; - + /* + int dimX { 16 }; + int dimY { 16 }; + int dimZ { 16 }; + */ int dimX { 16 }; int dimY { 16 }; int dimZ { 16 }; + bool freeze{ false }; + void setNumClusteredLights(int numLights) { numClusteredLights = numLights; emit dirty(); } + int numClusteredLights { 0 }; signals: void dirty(); @@ -175,7 +182,8 @@ public: bool doDrawGrid{ false }; bool doDrawClusterFromDepth { false }; - bool doDrawContent { false }; + // bool doDrawContent { false }; + bool doDrawContent { true }; signals: void dirty(); diff --git a/libraries/render-utils/src/LightStage.cpp b/libraries/render-utils/src/LightStage.cpp index bedd22b360..8c6e6d96a4 100644 --- a/libraries/render-utils/src/LightStage.cpp +++ b/libraries/render-utils/src/LightStage.cpp @@ -136,7 +136,7 @@ LightStage::LightPointer LightStage::removeLight(Index index) { void LightStage::updateLightArrayBuffer(Index lightId) { auto lightSize = sizeof(model::Light::LightSchema); if (!_lightArrayBuffer) { - _lightArrayBuffer = std::make_shared(); + _lightArrayBuffer = std::make_shared(lightSize); } assert(checkLightId(lightId)); diff --git a/libraries/render-utils/src/deferred_light_point.slv b/libraries/render-utils/src/deferred_light_point.slv index f126ee9251..88da7dd04c 100644 --- a/libraries/render-utils/src/deferred_light_point.slv +++ b/libraries/render-utils/src/deferred_light_point.slv @@ -20,10 +20,10 @@ <@include model/Light.slh@> -<$declareLightBuffer(120)$> +<$declareLightBuffer(256)$> uniform lightIndexBuffer { - int lightIndex[120]; + int lightIndex[256]; }; out vec4 _texCoord0; diff --git a/libraries/render-utils/src/deferred_light_spot.slv b/libraries/render-utils/src/deferred_light_spot.slv index 5edd889704..f9e81549dd 100755 --- a/libraries/render-utils/src/deferred_light_spot.slv +++ b/libraries/render-utils/src/deferred_light_spot.slv @@ -19,10 +19,10 @@ <$declareStandardTransform()$> <@include model/Light.slh@> -<$declareLightBuffer(120)$> +<$declareLightBuffer(256)$> uniform lightIndexBuffer { - int lightIndex[120]; + int lightIndex[256]; }; out vec4 _texCoord0; diff --git a/libraries/render-utils/src/lightClusters_drawClusterContent.slf b/libraries/render-utils/src/lightClusters_drawClusterContent.slf index fe8d850e8a..f4b9a82b64 100644 --- a/libraries/render-utils/src/lightClusters_drawClusterContent.slf +++ b/libraries/render-utils/src/lightClusters_drawClusterContent.slf @@ -16,7 +16,7 @@ <@include model/Light.slh@> -<$declareLightBuffer(128)$> +<$declareLightBuffer(256)$> <@include LightClusterGrid.slh@> diff --git a/libraries/render-utils/src/local_lights_shading.slf b/libraries/render-utils/src/local_lights_shading.slf index c7d49de979..b144ce13c7 100644 --- a/libraries/render-utils/src/local_lights_shading.slf +++ b/libraries/render-utils/src/local_lights_shading.slf @@ -19,7 +19,7 @@ // Everything about light <@include model/Light.slh@> -<$declareLightBuffer(128)$> +<$declareLightBuffer(256)$> <@include LightingModel.slh@> diff --git a/libraries/render-utils/src/spot_light.slf b/libraries/render-utils/src/spot_light.slf index 9d71832f15..4cacff86c4 100644 --- a/libraries/render-utils/src/spot_light.slf +++ b/libraries/render-utils/src/spot_light.slf @@ -19,9 +19,9 @@ // Everything about light <@include model/Light.slh@> -<$declareLightBuffer(32)$> +<$declareLightBuffer(256)$> uniform lightIndexBuffer { - int lightIndex[32]; + int lightIndex[256]; }; <@include LightingModel.slh@> diff --git a/scripts/developer/utilities/render/lightClustering.qml b/scripts/developer/utilities/render/lightClustering.qml index c772b9e88d..427a818239 100644 --- a/scripts/developer/utilities/render/lightClustering.qml +++ b/scripts/developer/utilities/render/lightClustering.qml @@ -106,6 +106,9 @@ Column { checked: Render.getConfig("DebugLightClusters")["doDrawContent"] onCheckedChanged: { Render.getConfig("DebugLightClusters")["doDrawContent"] = checked } } + Label { + text: "Num Cluster Items = " + Render.getConfig("LightClustering")["numClusteredLights"].toFixed(0) + } } } From 765355e5d1956eefe1695c377794ba7b6f0c53d1 Mon Sep 17 00:00:00 2001 From: samcake Date: Wed, 5 Oct 2016 18:30:03 -0700 Subject: [PATCH 61/75] Avoid the debug view by default --- libraries/render-utils/src/LightClusters.h | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/libraries/render-utils/src/LightClusters.h b/libraries/render-utils/src/LightClusters.h index e01d6c42f7..5402339563 100644 --- a/libraries/render-utils/src/LightClusters.h +++ b/libraries/render-utils/src/LightClusters.h @@ -24,7 +24,6 @@ public: float rangeFar { 200.0f }; float frustumFar { 10000.0f }; - // glm::ivec3 dims { 16, 16, 16 }; glm::ivec3 dims { 16, 16, 16 }; float spare; @@ -123,11 +122,7 @@ public: LightClusteringPassConfig() : render::Job::Config(true){} float rangeNear{ 0.1f }; float rangeFar{ 200.0f }; - /* - int dimX { 16 }; - int dimY { 16 }; - int dimZ { 16 }; - */ + int dimX { 16 }; int dimY { 16 }; int dimZ { 16 }; @@ -182,9 +177,8 @@ public: bool doDrawGrid{ false }; bool doDrawClusterFromDepth { false }; - // bool doDrawContent { false }; - bool doDrawContent { true }; - + bool doDrawContent { false }; + signals: void dirty(); From 621d62cdf8bc89a5e8f8b3a646ec13deb07f1878 Mon Sep 17 00:00:00 2001 From: samcake Date: Thu, 6 Oct 2016 09:53:12 -0700 Subject: [PATCH 62/75] Merge and fix the linux warning --- libraries/gpu/src/gpu/Buffer.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/gpu/src/gpu/Buffer.cpp b/libraries/gpu/src/gpu/Buffer.cpp index fb60e0e737..018788365d 100644 --- a/libraries/gpu/src/gpu/Buffer.cpp +++ b/libraries/gpu/src/gpu/Buffer.cpp @@ -42,8 +42,8 @@ Buffer::Size Buffer::getBufferGPUMemoryUsage() { } Buffer::Buffer(Size pageSize) : - _pages(pageSize), - _renderPages(pageSize) { + _renderPages(pageSize), + _pages(pageSize) { _bufferCPUCount++; } From 4504877ba6f30e899892bd771d1dd614fae00abe Mon Sep 17 00:00:00 2001 From: samcake Date: Thu, 6 Oct 2016 15:14:08 -0700 Subject: [PATCH 63/75] Add a finer culling test to avoid faulty discards --- libraries/render-utils/src/LightClusters.cpp | 60 +++++++++++++++++--- 1 file changed, 51 insertions(+), 9 deletions(-) diff --git a/libraries/render-utils/src/LightClusters.cpp b/libraries/render-utils/src/LightClusters.cpp index 98615a72ff..e51d8f2e4d 100644 --- a/libraries/render-utils/src/LightClusters.cpp +++ b/libraries/render-utils/src/LightClusters.cpp @@ -210,6 +210,23 @@ bool reduceSphereToPlane(const glm::vec4& sphere, const glm::vec4& plane, glm::v return false; } + +uint32_t scanLightVolumeBoxSlice(FrustumGrid& grid, const FrustumGrid::Planes planes[3], int zSlice, int yMin, int yMax, int xMin, int xMax, LightClusters::LightID lightId, const glm::vec4& eyePosRadius, + std::vector< std::vector>& clusterGrid) { + glm::ivec3 gridPosToOffset(1, grid.dims.x, grid.dims.x * grid.dims.y); + uint32_t numClustersTouched = 0; + + for (auto y = yMin; (y <= yMax); y++) { + for (auto x = xMin; (x <= xMax); x++) { + auto index = x + gridPosToOffset.y * y + gridPosToOffset.z * zSlice; + clusterGrid[index].emplace_back(lightId); + numClustersTouched++; + } + } + + return numClustersTouched; +} + uint32_t scanLightVolumeBox(FrustumGrid& grid, const FrustumGrid::Planes planes[3], int zMin, int zMax, int yMin, int yMax, int xMin, int xMax, LightClusters::LightID lightId, const glm::vec4& eyePosRadius, std::vector< std::vector>& clusterGrid) { glm::ivec3 gridPosToOffset(1, grid.dims.x, grid.dims.x * grid.dims.y); @@ -281,7 +298,7 @@ uint32_t scanLightVolumeSphere(FrustumGrid& grid, const FrustumGrid::Planes plan for (; (x <= xs); x++) { auto index = grid.frustumGrid_clusterToIndex(ivec3(x, y, z)); - if (index < (int) clusterGrid.size()) { + if (index < (int)clusterGrid.size()) { clusterGrid[index].emplace_back(lightId); numClustersTouched++; } else { @@ -301,7 +318,7 @@ uint32_t LightClusters::updateClusters() { _clusterGrid.clear(); _clusterGrid.resize(_numClusters, EMPTY_CLUSTER); - uint32_t maxNumIndices = (uint32_t) _clusterContent.size(); + uint32_t maxNumIndices = (uint32_t)_clusterContent.size(); _clusterContent.clear(); _clusterContent.resize(maxNumIndices, INVALID_LIGHT); @@ -329,8 +346,9 @@ uint32_t LightClusters::updateClusters() { continue; } float eyeZMin = eyeOri.z + radius; + bool beyondFar = false; if (eyeZMin < -theFrustumGrid.rangeFar) { - continue; + beyondFar = true; } // Get z slices @@ -349,7 +367,17 @@ uint32_t LightClusters::updateClusters() { // CLamp the z range zMin = std::max(0, zMin); - // zMax = std::min(zMax, theFrustumGrid.dims.z); + // zMax = std::min(zMax, theFrustumGrid.dims.z); + + auto xLeftDistance = radius - distanceToPlane(eyeOri, _gridPlanes[0][0]); + auto xRightDistance = radius + distanceToPlane(eyeOri, _gridPlanes[0].back()); + + auto yBottomDistance = radius - distanceToPlane(eyeOri, _gridPlanes[1][0]); + auto yTopDistance = radius + distanceToPlane(eyeOri, _gridPlanes[1].back()); + + if ((xLeftDistance < 0.f) || (xRightDistance < 0.f) || (yBottomDistance < 0.f) || (yTopDistance < 0.f)) { + continue; + } // find 2D corners of the sphere in grid int xMin { 0 }; @@ -384,10 +412,16 @@ uint32_t LightClusters::updateClusters() { glm::vec3 rightDir(eyeOriDirH.x * eyeToTangentCircleCosH - eyeOriDirH.z * eyeToTangentCircleSinH, 0.0f, eyeOriDirH.x * eyeToTangentCircleSinH + eyeOriDirH.z * eyeToTangentCircleCosH); auto lc = theFrustumGrid.frustumGrid_eyeToClusterDirH(leftDir); + if (lc > xMax) { + lc = xMin; + } auto rc = theFrustumGrid.frustumGrid_eyeToClusterDirH(rightDir); - + if (rc < 0) { + rc = xMax; + } xMin = std::max(xMin, lc); xMax = std::min(rc, xMax); + assert(xMin <= xMax); } if ((eyeOriLen2V > radius2)) { @@ -408,16 +442,24 @@ uint32_t LightClusters::updateClusters() { auto bc = theFrustumGrid.frustumGrid_eyeToClusterDirV(bottomDir); auto tc = theFrustumGrid.frustumGrid_eyeToClusterDirV(topDir); - + if (bc > yMax) { + bc = yMin; + } + if (tc < 0) { + tc = yMax; + } yMin = std::max(yMin, bc); yMax =std::min(tc, yMax); + assert(yMin <= yMax); } // now voxelize auto& clusterGrid = (isSpot ? clusterGridSpot : clusterGridPoint); - numClusterTouched += scanLightVolumeSphere(theFrustumGrid, _gridPlanes, zMin, zMax, yMin, yMax, xMin, xMax, lightId, glm::vec4(glm::vec3(eyeOri), radius), clusterGrid); - // numClusterTouched += scanLightVolumeBox(theFrustumGrid, _gridPlanes, zMin, zMax, yMin, yMax, xMin, xMax, lightId, glm::vec4(glm::vec3(eyeOri), radius), clusterGrid); - + if (beyondFar) { + numClusterTouched += scanLightVolumeBoxSlice(theFrustumGrid, _gridPlanes, zMin, yMin, yMax, xMin, xMax, lightId, glm::vec4(glm::vec3(eyeOri), radius), clusterGrid); + } else { + numClusterTouched += scanLightVolumeSphere(theFrustumGrid, _gridPlanes, zMin, zMax, yMin, yMax, xMin, xMax, lightId, glm::vec4(glm::vec3(eyeOri), radius), clusterGrid); + } } // Lights have been gathered now reexpress in terms of 2 sequential buffers From ac54533433891c7c661596ff1ff9e9e3498081f7 Mon Sep 17 00:00:00 2001 From: samcake Date: Thu, 6 Oct 2016 18:15:32 -0700 Subject: [PATCH 64/75] Adding more counters to understand the cullign bug --- libraries/render-utils/src/LightClusters.cpp | 17 +++++++---- libraries/render-utils/src/LightClusters.h | 9 +++++- .../utilities/render/lightClustering.qml | 28 ++++++++++++++----- 3 files changed, 41 insertions(+), 13 deletions(-) diff --git a/libraries/render-utils/src/LightClusters.cpp b/libraries/render-utils/src/LightClusters.cpp index e51d8f2e4d..dd7897b23e 100644 --- a/libraries/render-utils/src/LightClusters.cpp +++ b/libraries/render-utils/src/LightClusters.cpp @@ -311,7 +311,7 @@ uint32_t scanLightVolumeSphere(FrustumGrid& grid, const FrustumGrid::Planes plan return numClustersTouched; } -uint32_t LightClusters::updateClusters() { +glm::ivec3 LightClusters::updateClusters() { // Clean up last info std::vector< std::vector< LightIndex > > clusterGridPoint(_numClusters); std::vector< std::vector< LightIndex > > clusterGridSpot(_numClusters); @@ -327,11 +327,14 @@ uint32_t LightClusters::updateClusters() { glm::ivec3 gridPosToOffset(1, theFrustumGrid.dims.x, theFrustumGrid.dims.x * theFrustumGrid.dims.y); uint32_t numClusterTouched = 0; + uint32_t numLightsIn = _visibleLightIndices[0]; + uint32_t numClusteredLights = 0; for (size_t lightNum = 1; lightNum < _visibleLightIndices.size(); ++lightNum) { auto lightId = _visibleLightIndices[lightNum]; auto light = _lightStage->getLight(lightId); - if (!light) + if (!light) { continue; + } auto worldOri = light->getPosition(); auto radius = light->getMaximumRadius(); @@ -460,6 +463,8 @@ uint32_t LightClusters::updateClusters() { } else { numClusterTouched += scanLightVolumeSphere(theFrustumGrid, _gridPlanes, zMin, zMax, yMin, yMax, xMin, xMax, lightId, glm::vec4(glm::vec3(eyeOri), radius), clusterGrid); } + + numClusteredLights++; } // Lights have been gathered now reexpress in terms of 2 sequential buffers @@ -502,7 +507,7 @@ uint32_t LightClusters::updateClusters() { _clusterGridBuffer._buffer->setData(_clusterGridBuffer._size, (gpu::Byte*) _clusterGrid.data()); _clusterContentBuffer._buffer->setSubData(0, indexOffset * sizeof(LightIndex), (gpu::Byte*) _clusterContent.data()); - return numClusterTouched; + return glm::ivec3(numLightsIn, numClusteredLights, numClusterTouched); } @@ -543,12 +548,14 @@ void LightClusteringPass::run(const render::SceneContextPointer& sceneContext, c _lightClusters->updateLightStage(lightStage); _lightClusters->updateLightFrame(lightStage->_currentFrame, lightingModel->isPointLightEnabled(), lightingModel->isSpotLightEnabled()); - auto numClusterdLights = _lightClusters->updateClusters(); + auto clusteringStats = _lightClusters->updateClusters(); output = _lightClusters; auto config = std::static_pointer_cast(renderContext->jobConfig); - config->setNumClusteredLights(numClusterdLights); + config->setNumInputLights(clusteringStats.x); + config->setNumClusteredLights(clusteringStats.y); + config->setNumClusteredLightReferences(clusteringStats.z); } DebugLightClusters::DebugLightClusters() { diff --git a/libraries/render-utils/src/LightClusters.h b/libraries/render-utils/src/LightClusters.h index 5402339563..bb2bf47295 100644 --- a/libraries/render-utils/src/LightClusters.h +++ b/libraries/render-utils/src/LightClusters.h @@ -74,7 +74,7 @@ public: void updateLightFrame(const LightStage::Frame& lightFrame, bool points = true, bool spots = true); - uint32_t updateClusters(); + glm::ivec3 updateClusters(); ViewFrustum _frustum; @@ -117,6 +117,8 @@ class LightClusteringPassConfig : public render::Job::Config { Q_PROPERTY(bool freeze MEMBER freeze NOTIFY dirty) + Q_PROPERTY(int numClusteredLightReferences MEMBER numClusteredLightReferences NOTIFY dirty) + Q_PROPERTY(int numInputLights MEMBER numInputLights NOTIFY dirty) Q_PROPERTY(int numClusteredLights MEMBER numClusteredLights NOTIFY dirty) public: LightClusteringPassConfig() : render::Job::Config(true){} @@ -130,6 +132,11 @@ public: bool freeze{ false }; + void setNumClusteredLightReferences(int numRefs) { numClusteredLightReferences = numRefs; emit dirty(); } + int numClusteredLightReferences { 0 }; + + void setNumInputLights(int numLights) { numInputLights = numLights; emit dirty(); } + int numInputLights { 0 }; void setNumClusteredLights(int numLights) { numClusteredLights = numLights; emit dirty(); } int numClusteredLights { 0 }; signals: diff --git a/scripts/developer/utilities/render/lightClustering.qml b/scripts/developer/utilities/render/lightClustering.qml index 427a818239..a9ca05dff8 100644 --- a/scripts/developer/utilities/render/lightClustering.qml +++ b/scripts/developer/utilities/render/lightClustering.qml @@ -33,14 +33,28 @@ Column { label: "time", scale: 1, color: "#FFFFFF" + } + ] + } + + PlotPerf { + title: "Lights" + height: 50 + object: Render.getConfig("LightClustering") + valueUnit: "" + valueScale: 1 + valueNumDigits: "0" + plots: [ + { + object: Render.getConfig("LightClustering"), + prop: "numClusteredLights", + label: "visible", + color: "#D959FE" }, { - object: Render.getConfig("DrawLight"), - prop: "numDrawn", - unit: "", - scale: 0.01, - numDigits: 0, - label: "Lights", + object: Render.getConfig("LightClustering"), + prop: "numInputLights", + label: "input", color: "#FED959" } ] @@ -107,7 +121,7 @@ Column { onCheckedChanged: { Render.getConfig("DebugLightClusters")["doDrawContent"] = checked } } Label { - text: "Num Cluster Items = " + Render.getConfig("LightClustering")["numClusteredLights"].toFixed(0) + text: "Num Cluster Items = " + Render.getConfig("LightClustering")["numClusteredLightReferences"].toFixed(0) } } From 567adf651a9c747c676a422783515b26b62bedb9 Mon Sep 17 00:00:00 2001 From: sam Date: Fri, 7 Oct 2016 05:02:04 -0700 Subject: [PATCH 65/75] FOund 2 bugs causing the empty clusters. now back to working --- .../src/DeferredLightingEffect.cpp | 1 + libraries/render-utils/src/LightClusters.cpp | 13 +++++---- libraries/render-utils/src/LightClusters.h | 19 ++++++++---- libraries/render-utils/src/LightStage.cpp | 10 +++++++ libraries/render-utils/src/LightStage.h | 5 ++++ .../render/src/render/IndexedContainer.h | 10 +++++-- .../utilities/render/lightClustering.qml | 29 +++++++++++++++++++ 7 files changed, 74 insertions(+), 13 deletions(-) diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index 084ec0e746..0524466412 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -139,6 +139,7 @@ void DeferredLightingEffect::init() { // Add the global light to the light stage (for later shadow rendering) _globalLights.push_back(_lightStage->addLight(lp)); + _lightStage->addShadow(_globalLights[0]); } diff --git a/libraries/render-utils/src/LightClusters.cpp b/libraries/render-utils/src/LightClusters.cpp index dd7897b23e..7cfd609f1e 100644 --- a/libraries/render-utils/src/LightClusters.cpp +++ b/libraries/render-utils/src/LightClusters.cpp @@ -174,9 +174,7 @@ void LightClusters::updateLightFrame(const LightStage::Frame& lightFrame, bool p auto& srcPointLights = lightFrame._pointLights; auto& srcSpotLights = lightFrame._spotLights; int numPointLights = (int)srcPointLights.size(); - // int offsetPointLights = 0; int numSpotLights = (int)srcSpotLights.size(); - // int offsetSpotLights = numPointLights; _visibleLightIndices.resize(numPointLights + numSpotLights + 1); @@ -367,10 +365,8 @@ glm::ivec3 LightClusters::updateClusters() { continue; } - // CLamp the z range zMin = std::max(0, zMin); - // zMax = std::min(zMax, theFrustumGrid.dims.z); auto xLeftDistance = radius - distanceToPlane(eyeOri, _gridPlanes[0][0]); auto xRightDistance = radius + distanceToPlane(eyeOri, _gridPlanes[0].back()); @@ -389,8 +385,9 @@ glm::ivec3 LightClusters::updateClusters() { int yMax { theFrustumGrid.dims.y - 1 }; float radius2 = radius * radius; - auto eyeOriH = eyeOri; - auto eyeOriV = eyeOri; + + auto eyeOriH = glm::vec3(eyeOri); + auto eyeOriV = glm::vec3(eyeOri); eyeOriH.y = 0.0f; eyeOriV.x = 0.0f; @@ -490,6 +487,7 @@ glm::ivec3 LightClusters::updateClusters() { } } + // Encode the cluster grid: [ ContentOffset - 16bits, Num Point LIghts - 8bits, Num Spot Lights - 8bits] _clusterGrid[i] = (uint32_t)((0xFF000000 & (numLightsSpot << 24)) | (0x00FF0000 & (numLightsPoint << 16)) | (0x0000FFFF & offset)); @@ -553,6 +551,9 @@ void LightClusteringPass::run(const render::SceneContextPointer& sceneContext, c output = _lightClusters; auto config = std::static_pointer_cast(renderContext->jobConfig); + config->numSceneLights = lightStage->getNumLights(); + config->numFreeSceneLights = lightStage->getNumFreeLights(); + config->numAllocatedSceneLights = lightStage->getNumAllocatedLights(); config->setNumInputLights(clusteringStats.x); config->setNumClusteredLights(clusteringStats.y); config->setNumClusteredLightReferences(clusteringStats.z); diff --git a/libraries/render-utils/src/LightClusters.h b/libraries/render-utils/src/LightClusters.h index bb2bf47295..57acc74121 100644 --- a/libraries/render-utils/src/LightClusters.h +++ b/libraries/render-utils/src/LightClusters.h @@ -120,6 +120,11 @@ class LightClusteringPassConfig : public render::Job::Config { Q_PROPERTY(int numClusteredLightReferences MEMBER numClusteredLightReferences NOTIFY dirty) Q_PROPERTY(int numInputLights MEMBER numInputLights NOTIFY dirty) Q_PROPERTY(int numClusteredLights MEMBER numClusteredLights NOTIFY dirty) + + Q_PROPERTY(int numSceneLights MEMBER numSceneLights NOTIFY dirty) + Q_PROPERTY(int numFreeSceneLights MEMBER numFreeSceneLights NOTIFY dirty) + Q_PROPERTY(int numAllocatedSceneLights MEMBER numAllocatedSceneLights NOTIFY dirty) + public: LightClusteringPassConfig() : render::Job::Config(true){} float rangeNear{ 0.1f }; @@ -131,14 +136,18 @@ public: bool freeze{ false }; - - void setNumClusteredLightReferences(int numRefs) { numClusteredLightReferences = numRefs; emit dirty(); } - int numClusteredLightReferences { 0 }; - void setNumInputLights(int numLights) { numInputLights = numLights; emit dirty(); } + int numClusteredLightReferences { 0 }; int numInputLights { 0 }; - void setNumClusteredLights(int numLights) { numClusteredLights = numLights; emit dirty(); } int numClusteredLights { 0 }; + + void setNumClusteredLightReferences(int numRefs) { numClusteredLightReferences = numRefs; emit dirty(); } + void setNumInputLights(int numLights) { numInputLights = numLights; emit dirty(); } + void setNumClusteredLights(int numLights) { numClusteredLights = numLights; emit dirty(); } + + int numSceneLights { 0 }; + int numFreeSceneLights { 0 }; + int numAllocatedSceneLights { 0 }; signals: void dirty(); diff --git a/libraries/render-utils/src/LightStage.cpp b/libraries/render-utils/src/LightStage.cpp index 8c6e6d96a4..66a9797d3c 100644 --- a/libraries/render-utils/src/LightStage.cpp +++ b/libraries/render-utils/src/LightStage.cpp @@ -123,6 +123,16 @@ LightStage::Index LightStage::addLight(const LightPointer& light) { } } +LightStage::Index LightStage::addShadow(Index lightIndex) { + auto light = getLight(lightIndex); + Index shadowId = INVALID_INDEX; + if (light) { + shadowId = _shadows.newElement(std::make_shared(light)); + _descs[lightIndex].shadowId = shadowId; + } + return shadowId; +} + LightStage::LightPointer LightStage::removeLight(Index index) { LightPointer removed = _lights.freeElement(index); diff --git a/libraries/render-utils/src/LightStage.h b/libraries/render-utils/src/LightStage.h index 34575596dd..c2293ac099 100644 --- a/libraries/render-utils/src/LightStage.h +++ b/libraries/render-utils/src/LightStage.h @@ -80,11 +80,16 @@ public: Index findLight(const LightPointer& light) const; Index addLight(const LightPointer& light); + + Index addShadow(Index lightIndex); + LightPointer removeLight(Index index); bool checkLightId(Index index) const { return _lights.checkIndex(index); } Index getNumLights() const { return _lights.getNumElements(); } + Index getNumFreeLights() const { return _lights.getNumFreeIndices(); } + Index getNumAllocatedLights() const { return _lights.getNumAllocatedIndices(); } LightPointer getLight(Index lightId) const { return _lights.get(lightId); diff --git a/libraries/render/src/render/IndexedContainer.h b/libraries/render/src/render/IndexedContainer.h index 6250d4f4f1..bb1a9b72b7 100644 --- a/libraries/render/src/render/IndexedContainer.h +++ b/libraries/render/src/render/IndexedContainer.h @@ -31,6 +31,8 @@ namespace indexed_container { bool checkIndex(Index index) const { return ((index >= 0) && (index < _nextNewIndex)); } Index getNumIndices() const { return _nextNewIndex - (Index) _freeIndices.size(); } + Index getNumFreeIndices() const { return (Index) _freeIndices.size(); } + Index getNumAllocatedIndices() const { return _nextNewIndex; } Index allocateIndex() { if (_freeIndices.empty()) { @@ -74,12 +76,14 @@ namespace indexed_container { bool checkIndex(Index index) const { return _allocator.checkIndex(index); }; Index getNumElements() const { return _allocator.getNumIndices(); } + Index getNumFreeIndices() const { return _allocator.getNumFreeIndices(); } + Index getNumAllocatedIndices() const { return _allocator.getNumAllocatedIndices(); } Index newElement(const Element& e) { Index index = _allocator.allocateIndex(); if (index != INVALID_INDEX) { if (index < (Index) _elements.size()) { - _elements.emplace(_elements.begin() + index, e); + _elements[index] = e; } else { assert(index == _elements.size()); _elements.emplace_back(e); @@ -113,12 +117,14 @@ namespace indexed_container { bool checkIndex(Index index) const { return _allocator.checkIndex(index); }; Index getNumElements() const { return _allocator.getNumIndices(); } + Index getNumFreeIndices() const { return _allocator.getNumFreeIndices(); } + Index getNumAllocatedIndices() const { return _allocator.getNumAllocatedIndices(); } Index newElement(const ElementPtr& e) { Index index = _allocator.allocateIndex(); if (index != INVALID_INDEX) { if (index < (Index) _elements.size()) { - _elements.emplace(_elements.begin() + index, e); + _elements[index] = e; } else { assert(index == (Index) _elements.size()); _elements.emplace_back(e); diff --git a/scripts/developer/utilities/render/lightClustering.qml b/scripts/developer/utilities/render/lightClustering.qml index a9ca05dff8..4db7aa8c39 100644 --- a/scripts/developer/utilities/render/lightClustering.qml +++ b/scripts/developer/utilities/render/lightClustering.qml @@ -60,6 +60,35 @@ Column { ] } + PlotPerf { + title: "Scene Lights" + height: 80 + object: Render.getConfig("LightClustering") + valueUnit: "" + valueScale: 1 + valueNumDigits: "0" + plots: [ + { + object: Render.getConfig("LightClustering"), + prop: "numSceneLights", + label: "current", + color: "#00B4EF" + }, + { + object: Render.getConfig("LightClustering"), + prop: "numFreeSceneLights", + label: "free", + color: "#1AC567" + }, + { + object: Render.getConfig("LightClustering"), + prop: "numAllocatedSceneLights", + label: "allocated", + color: "#9495FF" + } + ] + } + ConfigSlider { label: qsTr("Range Near [m]") integral: false From 8a44140e6bc4a8b334a0ef31e78641b46ba7ac9a Mon Sep 17 00:00:00 2001 From: samcake Date: Fri, 7 Oct 2016 16:04:19 -0700 Subject: [PATCH 66/75] cleaning up the comments from review and trying something to adress the issue that showed up on i5 --- .../src/RenderableLightEntityItem.cpp | 24 ------ libraries/entities/src/EntityItem.h | 2 +- libraries/entities/src/LightEntityItem.h | 2 +- .../gpu-gl/src/gpu/gl/GLBackendQuery.cpp | 5 +- libraries/model/src/model/Light.cpp | 15 ---- libraries/model/src/model/Light.h | 28 +------ .../render-utils/src/LightClusterGrid.slh | 2 +- libraries/render-utils/src/LightClusters.cpp | 74 ++++++++++++------- libraries/render-utils/src/LightClusters.h | 12 ++- libraries/render-utils/src/LightPayload.cpp | 7 ++ 10 files changed, 69 insertions(+), 102 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableLightEntityItem.cpp b/libraries/entities-renderer/src/RenderableLightEntityItem.cpp index 4ae2da295f..2e55901bbd 100644 --- a/libraries/entities-renderer/src/RenderableLightEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableLightEntityItem.cpp @@ -89,30 +89,6 @@ void RenderableLightEntityItem::notifyChanged() { scene->enqueuePendingChanges(pendingChanges); } -/* -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::compMax(dimensions); - - - // DependencyManager::get()->addLight(_light); - -#ifdef WANT_DEBUG - Q_ASSERT(args->_batch); - gpu::Batch& batch = *args->_batch; - batch.setModelTransform(getTransformToCenter()); - DependencyManager::get()->renderWireSphere(batch, 0.5f, 15, 15, glm::vec4(color, 1.0f)); -#endif -}; -*/ - bool RenderableLightEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, bool& keepSearching, OctreeElementPointer& element, float& distance, BoxFace& face, glm::vec3& surfaceNormal, diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index e01e5e087c..7e06a59f06 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -90,7 +90,7 @@ public: virtual EntityItemProperties getProperties(EntityPropertyFlags desiredProperties = EntityPropertyFlags()) const; /// returns true if something changed - // THis function calls setSubClass properties and detects if any property changes value. + // This function calls setSubClass properties and detects if any property changes value. // If something changed then the "somethingChangedNotification" calls happens virtual bool setProperties(const EntityItemProperties& properties); diff --git a/libraries/entities/src/LightEntityItem.h b/libraries/entities/src/LightEntityItem.h index cb23c2357f..b9f02eead8 100644 --- a/libraries/entities/src/LightEntityItem.h +++ b/libraries/entities/src/LightEntityItem.h @@ -109,7 +109,7 @@ protected: float _cutoff { DEFAULT_CUTOFF }; // Dirty flag turn true when either light properties is changing values. - // THis gets back to false in the somethingChangedNotification() call + // This gets back to false in the somethingChangedNotification() call // Which is called after a setProperties() or a readEntitySubClassFromBUfferCall on the entity. bool _lightPropertiesChanged { false }; diff --git a/libraries/gpu-gl/src/gpu/gl/GLBackendQuery.cpp b/libraries/gpu-gl/src/gpu/gl/GLBackendQuery.cpp index 5fd1c4c6a3..c53e650aee 100644 --- a/libraries/gpu-gl/src/gpu/gl/GLBackendQuery.cpp +++ b/libraries/gpu-gl/src/gpu/gl/GLBackendQuery.cpp @@ -27,7 +27,6 @@ void GLBackend::do_beginQuery(const Batch& batch, size_t paramOffset) { if (glquery) { PROFILE_RANGE_BEGIN(glquery->_profileRangeId, query->getName().c_str(), 0xFFFF7F00); - //glGetInteger64v(GL_TIMESTAMP, (GLint64*)&glquery->_batchElapsedTime); glquery->_batchElapsedTime = usecTimestampNow() * 1000; if (timeElapsed) { glBeginQuery(GL_TIME_ELAPSED, glquery->_endqo); @@ -47,10 +46,8 @@ void GLBackend::do_endQuery(const Batch& batch, size_t paramOffset) { } else { glQueryCounter(glquery->_endqo, GL_TIMESTAMP); } - GLint64 now; - //glGetInteger64v(GL_TIMESTAMP, &now); - now = usecTimestampNow() * 1000; + GLint64 now = usecTimestampNow() * 1000; glquery->_batchElapsedTime = now - glquery->_batchElapsedTime; PROFILE_RANGE_END(glquery->_profileRangeId); diff --git a/libraries/model/src/model/Light.cpp b/libraries/model/src/model/Light.cpp index 59b57f274c..4ac0573cf6 100755 --- a/libraries/model/src/model/Light.cpp +++ b/libraries/model/src/model/Light.cpp @@ -44,7 +44,6 @@ void Light::setType(Type type) { } updateLightRadius(); } - updateVolumeGeometry(); } @@ -89,7 +88,6 @@ void Light::setMaximumRadius(float radius) { } _lightSchemaBuffer.edit().volume.radius = radius; updateLightRadius(); - updateVolumeGeometry(); } void Light::updateLightRadius() { @@ -125,8 +123,6 @@ void Light::setSpotAngle(float angle) { if (isSpot()) { _lightSchemaBuffer.edit().volume.spotCos = _spotCos; } - - updateVolumeGeometry(); } void Light::setSpotExponent(float exponent) { @@ -162,14 +158,3 @@ void Light::setAmbientMapNumMips(uint16_t numMips) { _ambientSchemaBuffer.edit().mapNumMips = (float)numMips; } -void Light::updateVolumeGeometry() { - // enlarge the scales slightly to account for tesselation - /* const float SCALE_EXPANSION = 0.05f; - glm::vec4 volumeGeometry(0.0f, 0.0f, 0.0f, getMaximumRadius() * (1.0f + SCALE_EXPANSION)); - - if (getType() == SPOT) { - const float TANGENT_LENGTH_SCALE = 0.666f; - volumeGeometry = glm::vec4(getSpotAngleCosSin(), TANGENT_LENGTH_SCALE * tanf(0.5f * getSpotAngle()), volumeGeometry.w); - } - editSchema()._volumeGeometry = volumeGeometry;*/ -} diff --git a/libraries/model/src/model/Light.h b/libraries/model/src/model/Light.h index b57b8c6095..947474bbfd 100755 --- a/libraries/model/src/model/Light.h +++ b/libraries/model/src/model/Light.h @@ -149,7 +149,7 @@ public: void setAmbientMapNumMips(uint16_t numMips); uint16_t getAmbientMapNumMips() const { return (uint16_t) _ambientSchemaBuffer->mapNumMips; } - // LIght Schema + // Light Schema class LightSchema { public: LightVolume volume; @@ -158,8 +158,8 @@ public: class AmbientSchema { public: - float intensity { 0.f }; - float mapNumMips { 0.f }; + float intensity { 0.0f }; + float mapNumMips { 0.0f }; float spare1; float spare2; gpu::SphericalHarmonics ambientSphere; @@ -168,27 +168,6 @@ public: using LightSchemaBuffer = gpu::StructBuffer; using AmbientSchemaBuffer = gpu::StructBuffer; - // Schema to access the attribute values of the light - /* class Schema { - public: - Vec4 _position{0.0f, 0.0f, 0.0f, 1.0f}; - Vec3 _direction{0.0f, 0.0f, -1.0f}; - float _ambientIntensity{0.0f}; - Color _color{1.0f}; - float _intensity{1.0f}; - Vec4 _attenuation{0.1f, 1.0f, 0.0f, 0.0f}; - Vec4 _spot{0.0f, 0.0f, 0.0f, 0.0f}; - //Vec4 _shadow{0.0f}; - - - float _ambientMapNumMips{ 0.0f }; - Vec3 _control{ 0.0f, 0.0f, 0.0f }; - - Vec4 _volumeGeometry { 1.f }; - - gpu::SphericalHarmonics _ambientSphere; - }; - */ const LightSchemaBuffer& getLightSchemaBuffer() const { return _lightSchemaBuffer; } const AmbientSchemaBuffer& getAmbientSchemaBuffer() const { return _ambientSchemaBuffer; } @@ -207,7 +186,6 @@ protected: float _spotCos { -1.0f }; // stored here to be able to reset the spot angle when turning the type spot on/off void updateLightRadius(); - void updateVolumeGeometry(); }; typedef std::shared_ptr< Light > LightPointer; diff --git a/libraries/render-utils/src/LightClusterGrid.slh b/libraries/render-utils/src/LightClusterGrid.slh index 3cd3bec473..f4ec35a75c 100644 --- a/libraries/render-utils/src/LightClusterGrid.slh +++ b/libraries/render-utils/src/LightClusterGrid.slh @@ -1,5 +1,5 @@ ()), _clusterGridBuffer(/*std::make_shared(), */gpu::Element::INDEX_INT32), _clusterContentBuffer(/*std::make_shared(), */gpu::Element::INDEX_INT32) { - auto dims = _frustumGridBuffer.edit().dims; - _frustumGridBuffer.edit().dims = ivec3(0); // make sure we go through the full reset of the dimensionts ion the setDImensions call - setDimensions(dims, MAX_GRID_DIMENSIONS.w); } void LightClusters::setDimensions(glm::uvec3 gridDims, uint32_t listBudget) { ivec3 configDimensions; auto gridBudget = MAX_GRID_DIMENSIONS.w; - configDimensions.x = std::min(MAX_GRID_DIMENSIONS.x, gridDims.x); - configDimensions.y = std::min(MAX_GRID_DIMENSIONS.y, gridDims.y); - configDimensions.z = std::min(MAX_GRID_DIMENSIONS.z, gridDims.z); + configDimensions.x = std::max(1, (int) std::min(MAX_GRID_DIMENSIONS.x, gridDims.x)); + configDimensions.y = std::max(1, (int) std::min(MAX_GRID_DIMENSIONS.y, gridDims.y)); + configDimensions.z = std::max(1, (int) std::min(MAX_GRID_DIMENSIONS.z, gridDims.z)); auto sliceCost = configDimensions.x * configDimensions.y; auto maxNumSlices = (int)(gridBudget / sliceCost) - 1; configDimensions.z = std::min(maxNumSlices, configDimensions.z); - static int numFrames = 0; - numFrames++; - auto& dims = _frustumGridBuffer->dims; - if ((numFrames == 10) || (dims.x != configDimensions.x) || (dims.y != configDimensions.y) || (dims.z != configDimensions.z)) { - _frustumGridBuffer.edit().dims = configDimensions; - _frustumGridBuffer.edit().generateGridPlanes(_gridPlanes[0], _gridPlanes[1], _gridPlanes[2]); - } - - auto numClusters = _frustumGridBuffer.edit().frustumGrid_numClusters(); - if (numClusters != _numClusters) { - _numClusters = numClusters; - _clusterGrid.clear(); - _clusterGrid.resize(_numClusters, EMPTY_CLUSTER); - // _clusterGridBuffer._size = _clusterGridBuffer._buffer->resize(_numClusters * sizeof(uint32_t)); - _clusterGridBuffer._size = (_numClusters * sizeof(uint32_t)); - _clusterGridBuffer._buffer = std::make_shared(_clusterGridBuffer._size, (gpu::Byte*) _clusterGrid.data(), _clusterGridBuffer._size); + // Grab the frustumGridBuffer and force it updated + const auto& constFrustumGrid = _frustumGridBuffer.get(); + const auto& dims = constFrustumGrid.dims; + if ((dims.x != configDimensions.x) || (dims.y != configDimensions.y) || (dims.z != configDimensions.z)) { + auto& theFrustumGrid = _frustumGridBuffer.edit(); + theFrustumGrid.dims = configDimensions; + theFrustumGrid.generateGridPlanes(_gridPlanes[0], _gridPlanes[1], _gridPlanes[2]); + _clusterResourcesInvalid = true; } auto configListBudget = std::min(MAX_GRID_DIMENSIONS.w, listBudget); + if (_clusterContentBudget != configListBudget) { + _clusterContentBudget = configListBudget; + _clusterResourcesInvalid = true; + } +} - // SInce LightINdex is 2bytes, we can fit 2 in a uint32 +uint32_t LightClusters::getNumClusters() const { + auto theFrustumGrid = _frustumGridBuffer.get(); + return theFrustumGrid.frustumGrid_numClusters(); +} + + void LightClusters::updateClusterResource() { + if (!_clusterResourcesInvalid) { + return; + } + _clusterResourcesInvalid = false; + auto numClusters = getNumClusters(); + if (numClusters != _clusterGrid.size()) { + _clusterGrid.clear(); + _clusterGrid.resize(numClusters, EMPTY_CLUSTER); + _clusterGridBuffer._size = (numClusters * sizeof(uint32_t)); + _clusterGridBuffer._buffer = std::make_shared(_clusterGridBuffer._size, (gpu::Byte*) _clusterGrid.data(), _clusterGridBuffer._size); + } + + // Since LightIndex is 2bytes, we can fit 2 in a uint32 + auto configListBudget = _clusterContentBudget; if (sizeof(LightIndex) == 2) { configListBudget *= 2; } @@ -129,9 +142,7 @@ void LightClusters::setDimensions(glm::uvec3 gridDims, uint32_t listBudget) { if (configListBudget != _clusterContent.size()) { _clusterContent.clear(); _clusterContent.resize(configListBudget, INVALID_LIGHT); - // _clusterContentBuffer._size = _clusterContentBuffer._buffer->resize(configListBudget * sizeof(LightIndex)); _clusterContentBuffer._size = (configListBudget * sizeof(LightIndex)); - // _clusterContentBuffer._buffer->setData(_clusterContentBuffer._size, (gpu::Byte*) _clusterContent.data()); _clusterContentBuffer._buffer = std::make_shared(_clusterContentBuffer._size, (gpu::Byte*) _clusterContent.data(), _clusterContentBuffer._size); } } @@ -310,16 +321,23 @@ uint32_t scanLightVolumeSphere(FrustumGrid& grid, const FrustumGrid::Planes plan } glm::ivec3 LightClusters::updateClusters() { + // Make sure resource are in good shape + updateClusterResource(); + // Clean up last info - std::vector< std::vector< LightIndex > > clusterGridPoint(_numClusters); - std::vector< std::vector< LightIndex > > clusterGridSpot(_numClusters); + uint32_t numClusters = (uint32_t)_clusterGrid.size(); + + std::vector< std::vector< LightIndex > > clusterGridPoint(numClusters); + std::vector< std::vector< LightIndex > > clusterGridSpot(numClusters); _clusterGrid.clear(); - _clusterGrid.resize(_numClusters, EMPTY_CLUSTER); + _clusterGrid.resize(numClusters, EMPTY_CLUSTER); + uint32_t maxNumIndices = (uint32_t)_clusterContent.size(); _clusterContent.clear(); _clusterContent.resize(maxNumIndices, INVALID_LIGHT); + auto theFrustumGrid(_frustumGridBuffer.get()); glm::ivec3 gridPosToOffset(1, theFrustumGrid.dims.x, theFrustumGrid.dims.x * theFrustumGrid.dims.y); diff --git a/libraries/render-utils/src/LightClusters.h b/libraries/render-utils/src/LightClusters.h index 57acc74121..450047b0ab 100644 --- a/libraries/render-utils/src/LightClusters.h +++ b/libraries/render-utils/src/LightClusters.h @@ -24,7 +24,7 @@ public: float rangeFar { 200.0f }; float frustumFar { 10000.0f }; - glm::ivec3 dims { 16, 16, 16 }; + glm::ivec3 dims { 1, 1, 1 }; float spare; glm::mat4 eyeToGridProj; @@ -68,6 +68,8 @@ public: void setDimensions(glm::uvec3 gridDims, uint32_t listBudget = MAX_GRID_DIMENSIONS.w); void setRangeNearFar(float rangeNear, float rangeFar); + uint32_t getNumClusters() const; + void updateFrustum(const ViewFrustum& frustum); void updateLightStage(const LightStagePointer& lightStage); @@ -76,8 +78,10 @@ public: glm::ivec3 updateClusters(); + ViewFrustum _frustum; + LightStagePointer _lightStage; @@ -89,8 +93,6 @@ public: LightStage::LightIndices _visibleLightIndices; gpu::BufferView _lightIndicesBuffer; - int32_t _numClusters { 0 }; - const uint32_t EMPTY_CLUSTER { 0x0000FFFF }; const LightID INVALID_LIGHT { LightStage::INVALID_INDEX }; @@ -100,6 +102,10 @@ public: std::vector _clusterContent; gpu::BufferView _clusterGridBuffer; gpu::BufferView _clusterContentBuffer; + int32_t _clusterContentBudget { 0 }; + + bool _clusterResourcesInvalid { true }; + void updateClusterResource(); }; using LightClustersPointer = std::shared_ptr; diff --git a/libraries/render-utils/src/LightPayload.cpp b/libraries/render-utils/src/LightPayload.cpp index 5f58677efe..a670c9f620 100644 --- a/libraries/render-utils/src/LightPayload.cpp +++ b/libraries/render-utils/src/LightPayload.cpp @@ -71,6 +71,13 @@ void LightPayload::render(RenderArgs* args) { if (isVisible()) { // FInally, push the light visible in the frame _stage->_currentFrame.pushLight(_index, _light->getType()); + +#ifdef WANT_DEBUG + Q_ASSERT(args->_batch); + gpu::Batch& batch = *args->_batch; + batch.setModelTransform(getTransformToCenter()); + DependencyManager::get()->renderWireSphere(batch, 0.5f, 15, 15, glm::vec4(color, 1.0f)); +#endif } } From 429a7cf58ae23cd21fd285c1053d81273dbc9104 Mon Sep 17 00:00:00 2001 From: samcake Date: Fri, 7 Oct 2016 16:12:36 -0700 Subject: [PATCH 67/75] adjust grid dimension to 14 x 14 x 14 conservatively to keep the generation fast --- libraries/render-utils/src/LightClusters.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/render-utils/src/LightClusters.h b/libraries/render-utils/src/LightClusters.h index 450047b0ab..13e5e19895 100644 --- a/libraries/render-utils/src/LightClusters.h +++ b/libraries/render-utils/src/LightClusters.h @@ -136,9 +136,9 @@ public: float rangeNear{ 0.1f }; float rangeFar{ 200.0f }; - int dimX { 16 }; - int dimY { 16 }; - int dimZ { 16 }; + int dimX { 14 }; + int dimY { 14 }; + int dimZ { 14 }; bool freeze{ false }; From 8476939ba9a6049af27a97f0e18b1efbc78309f5 Mon Sep 17 00:00:00 2001 From: samcake Date: Fri, 7 Oct 2016 16:44:51 -0700 Subject: [PATCH 68/75] Avoiding warnings maybe --- libraries/render-utils/src/LightClusters.cpp | 4 ++-- libraries/render-utils/src/LightClusters.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/render-utils/src/LightClusters.cpp b/libraries/render-utils/src/LightClusters.cpp index c96b56a457..c2559f847b 100644 --- a/libraries/render-utils/src/LightClusters.cpp +++ b/libraries/render-utils/src/LightClusters.cpp @@ -126,7 +126,7 @@ uint32_t LightClusters::getNumClusters() const { } _clusterResourcesInvalid = false; auto numClusters = getNumClusters(); - if (numClusters != _clusterGrid.size()) { + if (numClusters != (uint32_t) _clusterGrid.size()) { _clusterGrid.clear(); _clusterGrid.resize(numClusters, EMPTY_CLUSTER); _clusterGridBuffer._size = (numClusters * sizeof(uint32_t)); @@ -139,7 +139,7 @@ uint32_t LightClusters::getNumClusters() const { configListBudget *= 2; } - if (configListBudget != _clusterContent.size()) { + if (configListBudget != (uint32_t) _clusterContent.size()) { _clusterContent.clear(); _clusterContent.resize(configListBudget, INVALID_LIGHT); _clusterContentBuffer._size = (configListBudget * sizeof(LightIndex)); diff --git a/libraries/render-utils/src/LightClusters.h b/libraries/render-utils/src/LightClusters.h index 13e5e19895..9514066561 100644 --- a/libraries/render-utils/src/LightClusters.h +++ b/libraries/render-utils/src/LightClusters.h @@ -102,7 +102,7 @@ public: std::vector _clusterContent; gpu::BufferView _clusterGridBuffer; gpu::BufferView _clusterContentBuffer; - int32_t _clusterContentBudget { 0 }; + uint32_t _clusterContentBudget { 0 }; bool _clusterResourcesInvalid { true }; void updateClusterResource(); From 297907688c898e61ac6ea63d268671d96406bc7a Mon Sep 17 00:00:00 2001 From: samcake Date: Mon, 10 Oct 2016 12:43:33 -0700 Subject: [PATCH 69/75] Fixing reveiw comments --- libraries/gpu/src/gpu/Query.h | 4 ++-- libraries/model/src/model/LightIrradiance.shared.slh | 3 +-- libraries/render-utils/src/LightClusters.h | 10 ++++------ 3 files changed, 7 insertions(+), 10 deletions(-) diff --git a/libraries/gpu/src/gpu/Query.h b/libraries/gpu/src/gpu/Query.h index 26553d67b3..e053fdd507 100644 --- a/libraries/gpu/src/gpu/Query.h +++ b/libraries/gpu/src/gpu/Query.h @@ -42,7 +42,7 @@ namespace gpu { protected: Handler _returnHandler; - std::string _name; + const std::string _name; uint64_t _queryResult { 0 }; uint64_t _usecBatchElapsedTime { 0 }; }; @@ -67,7 +67,7 @@ namespace gpu { static const int QUERY_QUEUE_SIZE { 4 }; - std::string _name; + const std::string _name; gpu::Queries _timerQueries; int _headIndex = -1; int _tailIndex = -1; diff --git a/libraries/model/src/model/LightIrradiance.shared.slh b/libraries/model/src/model/LightIrradiance.shared.slh index eaa1b33a88..4a2ee40c9d 100644 --- a/libraries/model/src/model/LightIrradiance.shared.slh +++ b/libraries/model/src/model/LightIrradiance.shared.slh @@ -32,10 +32,9 @@ float lightIrradiance_getFalloffSpot(LightIrradiance li) { return li.attenuation float lightIrradiance_evalLightAttenuation(LightIrradiance li, float d) { float radius = lightIrradiance_getFalloffRadius(li); float cutoff = lightIrradiance_getCutoffRadius(li); - float denom = d / radius + 1.0; + float denom = (d / radius) + 1.0; float attenuation = 1.0 / (denom * denom); - // "Fade" the edges of light sources to make things look a bit more attractive. // Note: this tends to look a bit odd at lower exponents. attenuation *= min(1, max(0, -(d - cutoff))); diff --git a/libraries/render-utils/src/LightClusters.h b/libraries/render-utils/src/LightClusters.h index 9514066561..955e780b23 100644 --- a/libraries/render-utils/src/LightClusters.h +++ b/libraries/render-utils/src/LightClusters.h @@ -11,11 +11,13 @@ #ifndef hifi_render_utils_LightClusters_h #define hifi_render_utils_LightClusters_h +#include #include #include #include "LightStage.h" - -#include +#include "DeferredFrameTransform.h" +#include "LightingModel.h" +#include "SurfaceGeometryPass.h" class FrustumGrid { public: @@ -160,10 +162,6 @@ signals: protected: }; -#include "DeferredFrameTransform.h" -#include "LightingModel.h" -#include "SurfaceGeometryPass.h" - class LightClusteringPass { public: using Inputs = render::VaryingSet3; From 77062ac1b37e5ac4e29b321f145a24e4f9bbdea9 Mon Sep 17 00:00:00 2001 From: samcake Date: Tue, 11 Oct 2016 17:13:08 -0700 Subject: [PATCH 70/75] Cleaning up a missing constructor and adjusting the stride for the StrucBuffer by default + merging with upstream --- libraries/gpu/src/gpu/Buffer.h | 8 ++++---- libraries/render-utils/src/LightClusters.cpp | 11 +++++++++++ libraries/render-utils/src/LightClusters.h | 3 +++ 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/libraries/gpu/src/gpu/Buffer.h b/libraries/gpu/src/gpu/Buffer.h index 2079c60605..6b9306ebac 100644 --- a/libraries/gpu/src/gpu/Buffer.h +++ b/libraries/gpu/src/gpu/Buffer.h @@ -384,12 +384,12 @@ public: template class StructBuffer : public gpu::BufferView { public: - static BufferPointer makeBuffer() { - T t; - return std::make_shared(sizeof(T), (const gpu::Byte*) &t); + template static BufferPointer makeBuffer() { + U t; + return std::make_shared(sizeof(U), (const gpu::Byte*) &t, sizeof(U)); } ~StructBuffer() {}; - StructBuffer() : gpu::BufferView(makeBuffer()) {} + StructBuffer() : gpu::BufferView(makeBuffer()) {} T& edit() { diff --git a/libraries/render-utils/src/LightClusters.cpp b/libraries/render-utils/src/LightClusters.cpp index c2559f847b..f569351c55 100644 --- a/libraries/render-utils/src/LightClusters.cpp +++ b/libraries/render-utils/src/LightClusters.cpp @@ -44,6 +44,17 @@ enum LightClusterGridShader_BufferSlot { LIGHT_CLUSTER_GRID_CLUSTER_CONTENT_SLOT, }; +FrustumGrid::FrustumGrid(const FrustumGrid& source) : + frustumNear(source.frustumNear), + rangeNear(source.rangeNear), + rangeFar(source.rangeFar), + frustumFar(source.frustumFar), + dims(source.dims), + spare(source.spare), + eyeToGridProj(source.eyeToGridProj), + worldToEyeMat(source.worldToEyeMat), + eyeToWorldMat(source.eyeToWorldMat) +{} void FrustumGrid::generateGridPlanes(Planes& xPlanes, Planes& yPlanes, Planes& zPlanes) { xPlanes.resize(dims.x + 1); diff --git a/libraries/render-utils/src/LightClusters.h b/libraries/render-utils/src/LightClusters.h index 955e780b23..d27a6e1d92 100644 --- a/libraries/render-utils/src/LightClusters.h +++ b/libraries/render-utils/src/LightClusters.h @@ -33,6 +33,9 @@ public: glm::mat4 worldToEyeMat; glm::mat4 eyeToWorldMat; + FrustumGrid() = default; + FrustumGrid(const FrustumGrid& source); + void updateFrustum(const ViewFrustum& frustum) { frustumNear = frustum.getNearClip(); frustumFar = frustum.getFarClip(); From 7956c7b10b7a6c22245341e30248717dbc81821d Mon Sep 17 00:00:00 2001 From: samcake Date: Wed, 12 Oct 2016 09:57:06 -0700 Subject: [PATCH 71/75] Fixing a mistake introduced in previous commit in a shader --- libraries/render-utils/src/DeferredGlobalLight.slh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/render-utils/src/DeferredGlobalLight.slh b/libraries/render-utils/src/DeferredGlobalLight.slh index 9ccee8c43f..57ca33eaca 100755 --- a/libraries/render-utils/src/DeferredGlobalLight.slh +++ b/libraries/render-utils/src/DeferredGlobalLight.slh @@ -156,7 +156,7 @@ vec3 evalLightmappedColor(mat4 invViewMat, float shadowAttenuation, float obscur vec3 diffuseLight = lightAttenuation * lightmap; // Ambient light is the lightmap when in shadow - vec3 ambientLight = (1.0 - lightAttenuation) * lightmap * getLightAmbientIntensity(light); + vec3 ambientLight = (1.0 - lightAttenuation) * lightmap * getLightAmbientIntensity(ambient); return isLightmapEnabled() * obscurance * albedo * (diffuseLight + ambientLight); } From af438ae31bb62bad94df122076457c526a7a2637 Mon Sep 17 00:00:00 2001 From: samcake Date: Mon, 7 Nov 2016 17:56:54 -0800 Subject: [PATCH 72/75] Fix the buid --- libraries/gpu/src/gpu/Context.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/gpu/src/gpu/Context.cpp b/libraries/gpu/src/gpu/Context.cpp index 4344cd4d2c..108ed07916 100644 --- a/libraries/gpu/src/gpu/Context.cpp +++ b/libraries/gpu/src/gpu/Context.cpp @@ -36,7 +36,7 @@ void Context::beginFrame(const glm::mat4& renderPose) { _currentFrame->pose = renderPose; if (!_frameRangeTimer) { - _frameRangeTimer = std::make_shared(); + _frameRangeTimer = std::make_shared("gpu::Context::Frame"); } } From 1d3fc1b64797d4f7e57a93537c9c6dcbd531f8aa Mon Sep 17 00:00:00 2001 From: samcake Date: Thu, 10 Nov 2016 17:57:11 -0800 Subject: [PATCH 73/75] Fix a bad conversion to integer for negative values of the GRid COordinates --- libraries/render-utils/src/LightClusterGrid_shared.slh | 3 ++- .../render-utils/src/lightClusters_drawClusterContent.slf | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/libraries/render-utils/src/LightClusterGrid_shared.slh b/libraries/render-utils/src/LightClusterGrid_shared.slh index d5bde79056..ed0ed8d04d 100644 --- a/libraries/render-utils/src/LightClusterGrid_shared.slh +++ b/libraries/render-utils/src/LightClusterGrid_shared.slh @@ -136,6 +136,7 @@ ivec3 frustumGrid_eyeToClusterPos(vec3 eyePos) { vec3 volumePos = frustumGrid_eyeToVolume(eyePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar); + vec3 gridPos = frustumGrid_volumeToGrid(volumePos, frustumGrid.dims); if (gridPos.z >= frustumGrid.dims.z) { @@ -143,7 +144,7 @@ ivec3 frustumGrid_eyeToClusterPos(vec3 eyePos) { } - return ivec3(gridPos); + return ivec3(floor(gridPos)); } int frustumGrid_eyeToClusterDirH(vec3 eyeDir) { diff --git a/libraries/render-utils/src/lightClusters_drawClusterContent.slf b/libraries/render-utils/src/lightClusters_drawClusterContent.slf index f4b9a82b64..447f8bd634 100644 --- a/libraries/render-utils/src/lightClusters_drawClusterContent.slf +++ b/libraries/render-utils/src/lightClusters_drawClusterContent.slf @@ -38,9 +38,9 @@ void main(void) { // From frag world pos find the cluster vec4 clusterEyePos = frustumGrid_worldToEye(fragWorldPos); ivec3 clusterPos = frustumGrid_eyeToClusterPos(clusterEyePos.xyz); + int clusterIndex = frustumGrid_clusterToIndex(clusterPos); - - ivec3 cluster = clusterGrid_getCluster(frustumGrid_clusterToIndex(clusterPos)); + ivec3 cluster = clusterGrid_getCluster(clusterIndex); int numLights = cluster.x + cluster.y; float numLightsScale = clamp(numLights * 0.05, 0.01, 1.0); From dfc0b7beac31630329f56ff9e0260ed76cf64ce2 Mon Sep 17 00:00:00 2001 From: samcake Date: Tue, 22 Nov 2016 10:15:49 -0800 Subject: [PATCH 74/75] adressed reveiw comments --- .../src/RenderableLightEntityItem.cpp | 16 ++--- .../src/RenderableLightEntityItem.h | 2 +- libraries/entities/src/EntityItem.h | 3 +- .../src/DeferredLightingEffect.cpp | 65 ------------------- 4 files changed, 11 insertions(+), 75 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableLightEntityItem.cpp b/libraries/entities-renderer/src/RenderableLightEntityItem.cpp index 2e55901bbd..a7fcbf53ae 100644 --- a/libraries/entities-renderer/src/RenderableLightEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableLightEntityItem.cpp @@ -31,7 +31,7 @@ bool RenderableLightEntityItem::addToScene(EntityItemPointer self, std::shared_p _myItem = scene->allocateID(); auto renderItem = std::make_shared(); - updateRenderItemFromEntity(renderItem.get()); + updateRenderItemFromEntity((*renderItem)); auto renderPayload = std::make_shared(renderItem); @@ -109,24 +109,24 @@ void RenderableLightEntityItem::updateLightFromEntity(render::PendingChanges& pe } - pendingChanges.updateItem(_myItem, [this](LightPayload& data) { - this->updateRenderItemFromEntity(&data); + pendingChanges.updateItem(_myItem, [&](LightPayload& data) { + updateRenderItemFromEntity(data); }); } -void RenderableLightEntityItem::updateRenderItemFromEntity(LightPayload* lightPayload) { +void RenderableLightEntityItem::updateRenderItemFromEntity(LightPayload& lightPayload) { auto entity = this; - lightPayload->setVisible(entity->getVisible()); + lightPayload.setVisible(entity->getVisible()); - auto light = lightPayload->editLight(); + auto light = lightPayload.editLight(); light->setPosition(entity->getPosition()); light->setOrientation(entity->getRotation()); bool success; - lightPayload->editBound() = entity->getAABox(success); + lightPayload.editBound() = entity->getAABox(success); if (!success) { - lightPayload->editBound() = render::Item::Bound(); + lightPayload.editBound() = render::Item::Bound(); } glm::vec3 dimensions = entity->getDimensions(); diff --git a/libraries/entities-renderer/src/RenderableLightEntityItem.h b/libraries/entities-renderer/src/RenderableLightEntityItem.h index d37fa30318..36ba0d6311 100644 --- a/libraries/entities-renderer/src/RenderableLightEntityItem.h +++ b/libraries/entities-renderer/src/RenderableLightEntityItem.h @@ -49,7 +49,7 @@ private: // Dirty flag turn true when either setSubClassProperties or readEntitySubclassDataFromBuffer is changing a value - void updateRenderItemFromEntity(LightPayload* lightPayload); + void updateRenderItemFromEntity(LightPayload& lightPayload); }; diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index fffdd2e0ff..8100d02e1c 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -95,7 +95,8 @@ public: virtual bool setProperties(const EntityItemProperties& properties); // Set properties for sub class so they can add their own properties - // it does nothing in the root eclass + // it does nothing in the root class + // This function is called by setProperties which then can detects if any property changes value in the SubClass (see aboe comment on setProperties) virtual bool setSubClassProperties(const EntityItemProperties& properties) { return false; } // Update properties with empty parent id and globalized/absolute values (applying offset), and apply (non-empty) log template to args id, name-or-type, parent id. diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index c365ab6a9f..872aac974e 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -719,36 +719,9 @@ void RenderDeferredLocals::run(const render::SceneContextPointer& sceneContext, auto textureFrameTransform = gpu::Framebuffer::evalSubregionTexcoordTransformCoefficients(deferredFramebuffer->getFrameSize(), viewport); - // batch.setProjectionTransform(projMat); - // batch.setViewTransform(viewTransform, true); - // gather lights - /* auto& srcPointLights = deferredLightingEffect->_pointLights; - auto& srcSpotLights = deferredLightingEffect->_spotLights; - int numPointLights = (int) srcPointLights.size(); - int offsetPointLights = 0; - int numSpotLights = (int) srcSpotLights.size(); - int offsetSpotLights = numPointLights; - - - std::vector lightIndices(numPointLights + numSpotLights + 1); - lightIndices[0] = 0; - - if (points && !srcPointLights.empty()) { - memcpy(lightIndices.data() + (lightIndices[0] + 1), srcPointLights.data(), srcPointLights.size() * sizeof(int)); - lightIndices[0] += (int)srcPointLights.size(); - } - if (spots && !srcSpotLights.empty()) { - memcpy(lightIndices.data() + (lightIndices[0] + 1), srcSpotLights.data(), srcSpotLights.size() * sizeof(int)); - lightIndices[0] += (int)srcSpotLights.size(); - }*/ - //auto lightClusters = deferredLightingEffect->_lightClusters; auto& lightIndices = lightClusters->_visibleLightIndices; if (!lightIndices.empty() && lightIndices[0] > 0) { - // _localLightsBuffer._buffer->setData(lightIndices.size() * sizeof(int), (const gpu::Byte*) lightIndices.data()); - // _localLightsBuffer._size = lightIndices.size() * sizeof(int); - - // Bind the global list of lights and the visible lights this frame batch.setUniformBuffer(deferredLightingEffect->_localLightLocations->lightBufferUnit, lightClusters->_lightStage->_lightArrayBuffer); @@ -756,44 +729,6 @@ void RenderDeferredLocals::run(const render::SceneContextPointer& sceneContext, batch.setUniformBuffer(LIGHT_CLUSTER_GRID_CLUSTER_GRID_SLOT, lightClusters->_clusterGridBuffer); batch.setUniformBuffer(LIGHT_CLUSTER_GRID_CLUSTER_CONTENT_SLOT, lightClusters->_clusterContentBuffer); - - // before we get to the real lighting, let s try to cull down the number of pixels - if (false) {/* - if (numPointLights > 0) { - auto mesh = deferredLightingEffect->getPointLightMesh(); - batch.setIndexBuffer(mesh->getIndexBuffer()); - batch.setInputBuffer(0, mesh->getVertexBuffer()); - batch.setInputFormat(mesh->getVertexFormat()); - auto& pointPart = mesh->getPartBuffer().get(0); - - // Point light pipeline - batch.setPipeline(deferredLightingEffect->_pointLightBack); - - batch.drawIndexedInstanced(numPointLights, model::Mesh::topologyToPrimitive(pointPart._topology), pointPart._numIndices, pointPart._startIndex, offsetPointLights); - - batch.setPipeline(deferredLightingEffect->_pointLightFront); - - batch.drawIndexedInstanced(numPointLights, model::Mesh::topologyToPrimitive(pointPart._topology), pointPart._numIndices, pointPart._startIndex, offsetPointLights); - } - - if (numSpotLights > 0) { - auto mesh = deferredLightingEffect->getSpotLightMesh(); - batch.setIndexBuffer(mesh->getIndexBuffer()); - batch.setInputBuffer(0, mesh->getVertexBuffer()); - batch.setInputFormat(mesh->getVertexFormat()); - auto& conePart = mesh->getPartBuffer().get(0); - - // Spot light pipeline - batch.setPipeline(deferredLightingEffect->_spotLightBack); - - batch.drawIndexedInstanced(numSpotLights, model::Mesh::topologyToPrimitive(conePart._topology), conePart._numIndices, conePart._startIndex, offsetSpotLights); - - batch.setPipeline(deferredLightingEffect->_spotLightFront); - - batch.drawIndexedInstanced(numSpotLights, model::Mesh::topologyToPrimitive(conePart._topology), conePart._numIndices, conePart._startIndex, offsetSpotLights); - }*/ - } - // Local light pipeline batch.setPipeline(deferredLightingEffect->_localLight); batch._glUniform4fv(deferredLightingEffect->_localLightLocations->texcoordFrameTransform, 1, reinterpret_cast(&textureFrameTransform)); From d764eebc79370e1ac17e50a73ea5611b7791f25b Mon Sep 17 00:00:00 2001 From: samcake Date: Tue, 22 Nov 2016 12:10:56 -0800 Subject: [PATCH 75/75] removing dead code --- libraries/render-utils/src/LightClusters.cpp | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/libraries/render-utils/src/LightClusters.cpp b/libraries/render-utils/src/LightClusters.cpp index 829d84e883..d3a384f1df 100644 --- a/libraries/render-utils/src/LightClusters.cpp +++ b/libraries/render-utils/src/LightClusters.cpp @@ -726,13 +726,7 @@ void DebugLightClusters::run(const render::SceneContextPointer& sceneContext, co // Then the actual ClusterGrid attributes batch.setModelTransform(Transform()); - - // Bind the G-Buffer surfaces -/* batch.setResourceTexture(DEFERRED_BUFFER_COLOR_UNIT, deferredFramebuffer->getDeferredColorTexture()); - batch.setResourceTexture(DEFERRED_BUFFER_NORMAL_UNIT, deferredFramebuffer->getDeferredNormalTexture()); - batch.setResourceTexture(DEFERRED_BUFFER_EMISSIVE_UNIT, deferredFramebuffer->getDeferredSpecularTexture()); - batch.setResourceTexture(DEFERRED_BUFFER_DEPTH_UNIT, deferredFramebuffer->getPrimaryDepthTexture()); -*/ + // Bind the Light CLuster data strucutre batch.setUniformBuffer(LIGHT_GPU_SLOT, lightClusters->_lightStage->_lightArrayBuffer); batch.setUniformBuffer(LIGHT_CLUSTER_GRID_FRUSTUM_GRID_SLOT, lightClusters->_frustumGridBuffer); batch.setUniformBuffer(LIGHT_CLUSTER_GRID_CLUSTER_GRID_SLOT, lightClusters->_clusterGridBuffer);