From 2a0e67ee2a84e4cae2df5d6c4c0ffa1a40e8d8f2 Mon Sep 17 00:00:00 2001 From: samcake Date: Thu, 29 Sep 2016 19:06:26 -0700 Subject: [PATCH] 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); }