From 96935504a14cb48779812bae7d646a709caaf892 Mon Sep 17 00:00:00 2001 From: samcake Date: Thu, 1 Sep 2016 15:20:14 -0700 Subject: [PATCH] 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);