From 8e1eebbbd4063b8979c17643a4f935021d8693c8 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Wed, 4 Feb 2015 17:24:23 -0800 Subject: [PATCH] FInally getting the angular attenuation --- libraries/model/src/model/Light.cpp | 11 +++-- libraries/model/src/model/Light.h | 5 ++- .../src/DeferredLightingEffect.cpp | 31 +------------ libraries/render-utils/src/Light.slh | 9 ++-- libraries/render-utils/src/point_light.slf | 42 +++++++++--------- libraries/render-utils/src/spot_light.slf | 44 +++++++------------ 6 files changed, 54 insertions(+), 88 deletions(-) diff --git a/libraries/model/src/model/Light.cpp b/libraries/model/src/model/Light.cpp index 6348ffbcc7..a658c57be9 100755 --- a/libraries/model/src/model/Light.cpp +++ b/libraries/model/src/model/Light.cpp @@ -31,6 +31,7 @@ Light& Light::operator= (const Light& light) { _flags = (light._flags); _schemaBuffer = (light._schemaBuffer); _transform = (light._transform); + _spotConeAngle = (light._spotConeAngle); return (*this); } @@ -67,7 +68,7 @@ void Light::setMaximumRadius(float radius) { if (radius <= 0.f) { radius = 1.0f; } - float CutOffIntensityRatio = 0.01f; + float CutOffIntensityRatio = 0.05f; float surfaceRadius = radius / (sqrt(1.0f / CutOffIntensityRatio) - 1.f); editSchema()._attenuation = Vec4(surfaceRadius, 1.0f/surfaceRadius, CutOffIntensityRatio, radius); } @@ -76,15 +77,17 @@ void Light::setSpotCone(float angle) { if (angle <= 0.f) { angle = 0.0f; } - editSchema()._spot.x = cos(angle); - editSchema()._spot.z = angle; + float cosAngle = cos(angle); + editSchema()._spot.x = cosAngle; + editSchema()._spot.y = sin(angle); + editSchema()._spot.z = 1.0f / cosAngle; + _spotConeAngle = angle; } void Light::setSpotConeExponent(float exponent) { if (exponent <= 0.f) { exponent = 1.0f; } - editSchema()._spot.y = exponent; editSchema()._spot.w = exponent; } diff --git a/libraries/model/src/model/Light.h b/libraries/model/src/model/Light.h index 5e3bda5e1d..c1b8a351e5 100755 --- a/libraries/model/src/model/Light.h +++ b/libraries/model/src/model/Light.h @@ -81,7 +81,7 @@ public: bool isSpot() const { return getType() == SPOT; } void setSpotCone(float angle); void setSpotConeExponent(float exponent); - float getSpotConeAngle() const { return getSchema()._spot.z; } + float getSpotConeAngle() const { return _spotConeAngle; } float getSpotConeExponent() const { return getSchema()._spot.w; } // Schema to access the attribute values of the light @@ -105,7 +105,7 @@ public: _color(1.0f), _intensity(1.0f), _attenuation(1.0f, 1.0f, 1.0f, 1.0f), - _spot(0.0f, 0.0f, 0.0f, 0.0f), + _spot(0.0f, 0.0f, 0.0f, 3.0f), _control(0.0f) {} }; @@ -117,6 +117,7 @@ protected: Flags _flags; UniformBufferView _schemaBuffer; Transform _transform; + float _spotConeAngle = 0.0f; const Schema& getSchema() const { return _schemaBuffer.get(); } Schema& editSchema() { return _schemaBuffer.edit(); } diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index fee3b4c947..e0fd3787f6 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -304,6 +304,7 @@ void DeferredLightingEffect::addSpotLight(const glm::vec3& position, float radiu lp->setDirection(direction); lp->setMaximumRadius(radius); lp->setSpotCone(cutoff); + lp->setSpotConeExponent(exponent); lp->setColor(diffuse); lp->setIntensity(1.0f); lp->setType(model::Light::SPOT); @@ -470,25 +471,14 @@ void DeferredLightingEffect::render() { for (auto lightID : _pointLights) { auto light = _allocatedLights[lightID]; - // foreach (const PointLight& light, _pointLights) { + if (_pointLightLocations.lightBufferUnit >= 0) { gpu::Batch batch; batch.setUniformBuffer(_pointLightLocations.lightBufferUnit, light->getSchemaBuffer()); gpu::GLBackend::renderBatch(batch); } glUniformMatrix4fv(_pointLightLocations.invViewMat, 1, false, reinterpret_cast< const GLfloat* >(&invViewMat)); - -/* - _pointLight.setUniformValue(_pointLightLocations.radius, light.radius); - glLightfv(GL_LIGHT1, GL_AMBIENT, (const GLfloat*)&light.ambient); - glLightfv(GL_LIGHT1, GL_DIFFUSE, (const GLfloat*)&light.diffuse); - glLightfv(GL_LIGHT1, GL_SPECULAR, (const GLfloat*)&light.specular); - glLightfv(GL_LIGHT1, GL_POSITION, (const GLfloat*)&light.position); - glLightf(GL_LIGHT1, GL_CONSTANT_ATTENUATION, (light.constantAttenuation > 0.0f ? light.constantAttenuation : 0.0f)); - glLightf(GL_LIGHT1, GL_LINEAR_ATTENUATION, (light.linearAttenuation > 0.0f ? light.linearAttenuation : 0.0f)); - glLightf(GL_LIGHT1, GL_QUADRATIC_ATTENUATION, (light.quadraticAttenuation > 0.0f ? light.quadraticAttenuation : 0.0f)); - */ glPushMatrix(); float expandedRadius = light->getMaximumRadius() * (1.0f + SCALE_EXPANSION); @@ -527,7 +517,6 @@ void DeferredLightingEffect::render() { for (auto lightID : _spotLights) { auto light = _allocatedLights[lightID]; - // foreach (const SpotLight& light, _spotLights) { if (_spotLightLocations.lightBufferUnit >= 0) { gpu::Batch batch; batch.setUniformBuffer(_spotLightLocations.lightBufferUnit, light->getSchemaBuffer()); @@ -535,22 +524,6 @@ void DeferredLightingEffect::render() { } glUniformMatrix4fv(_spotLightLocations.invViewMat, 1, false, reinterpret_cast< const GLfloat* >(&invViewMat)); - // _spotLight.setUniformValue(_spotLightLocations.radius, light->getAttenuationRadius()); - - /* - _spotLight.setUniformValue(_spotLightLocations.radius, light.radius); - glLightfv(GL_LIGHT1, GL_AMBIENT, (const GLfloat*)&light.ambient); - glLightfv(GL_LIGHT1, GL_DIFFUSE, (const GLfloat*)&light.diffuse); - glLightfv(GL_LIGHT1, GL_SPECULAR, (const GLfloat*)&light.specular); - glLightfv(GL_LIGHT1, GL_POSITION, (const GLfloat*)&light.position); - glLightf(GL_LIGHT1, GL_CONSTANT_ATTENUATION, (light.constantAttenuation > 0.0f ? light.constantAttenuation : 0.0f)); - glLightf(GL_LIGHT1, GL_LINEAR_ATTENUATION, (light.linearAttenuation > 0.0f ? light.linearAttenuation : 0.0f)); - glLightf(GL_LIGHT1, GL_QUADRATIC_ATTENUATION, (light.quadraticAttenuation > 0.0f ? light.quadraticAttenuation : 0.0f)); - glLightfv(GL_LIGHT1, GL_SPOT_DIRECTION, (const GLfloat*)&light.direction); - glLightf(GL_LIGHT1, GL_SPOT_EXPONENT, light.exponent); - glLightf(GL_LIGHT1, GL_SPOT_CUTOFF, glm::degrees(light.cutoff)); - */ - glPushMatrix(); float expandedRadius = light->getMaximumRadius() * (1.0f + SCALE_EXPANSION); diff --git a/libraries/render-utils/src/Light.slh b/libraries/render-utils/src/Light.slh index ccf6e52836..ab9bf216de 100755 --- a/libraries/render-utils/src/Light.slh +++ b/libraries/render-utils/src/Light.slh @@ -41,11 +41,12 @@ 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) { - if (cosA > l._spot.x) { - return 0.0; - } - return clamp(pow(cosA / l._spot.x, l._spot.w), 0.0, 1.0); + return pow(cosA * l._spot.z, l._spot.w); } float getLightSquareRadius(Light l) { diff --git a/libraries/render-utils/src/point_light.slf b/libraries/render-utils/src/point_light.slf index da2d708f06..4a96f3ae3d 100644 --- a/libraries/render-utils/src/point_light.slf +++ b/libraries/render-utils/src/point_light.slf @@ -15,6 +15,9 @@ // Everything about deferred buffer <@include DeferredBuffer.slh@> +//Everything about deferred lighting +<@include DeferredLighting.slh@> + // Everything about light <@include Light.slh@> @@ -22,9 +25,8 @@ uniform mat4 invViewMat; void main(void) { - // get the depth and exit early if it doesn't pass the test + // Grab the fragment data from the uv vec2 texCoord = gl_TexCoord[0].st / gl_TexCoord[0].q; - DeferredFragment frag = unpackDeferredFragment(texCoord); // Kill if in front of the light volume @@ -37,9 +39,8 @@ void main(void) { Light light = getLight(); // Make the Light vector going from fragment to light center in world space - vec4 wPos; - wPos = invViewMat * frag.position; - vec3 fragLightVec = getLightPosition(light) - wPos.xyz; + vec4 fragPos = invViewMat * frag.position; + vec3 fragLightVec = getLightPosition(light) - fragPos.xyz; // Kill if too far from the light center if (dot(fragLightVec, fragLightVec) > getLightSquareRadius(light)) { @@ -48,31 +49,28 @@ void main(void) { // Allright we re valid in the volume float fragLightDistance = length(fragLightVec); - float lightAttenuation = evalLightAttenuation(light, fragLightDistance); - vec3 fragLightDir = fragLightVec / fragLightDistance; - vec4 wNor = invViewMat * vec4(frag.normal, 0.0); + + + // Eval shading + vec3 fragNormal = vec3(invViewMat * vec4(frag.normal, 0.0)); vec4 fragEyeVector = invViewMat * vec4(-frag.position.xyz, 0.0); vec3 fragEyeDir = normalize(fragEyeVector.xyz); - vec3 wHalfDir = normalize(fragEyeDir + fragLightDir); + vec4 shading = evalFragShading(fragNormal, fragLightDir, fragEyeDir, frag.specular, frag.gloss); - // Diffuse Lighting - float diffuseDot = dot(wNor.xyz, fragLightDir); - float facingLight = step(0.0, diffuseDot); - vec3 diffuseColor = frag.diffuse * diffuseDot * facingLight; - - // compute the specular multiplier (sans exponent) - float specularPower = facingLight * max(0.0, - dot(fragEyeDir, wHalfDir)); - vec3 specularColor = pow(specularPower, frag.gloss * 128.0) * frag.specular; + // Eval attenuation + float radialAttenuation = evalLightAttenuation(light, fragLightDistance); + // Final Lighting color + vec3 fragColor = shading.w * (frag.diffuse + shading.xyz); + gl_FragColor = vec4(fragColor * radialAttenuation * getLightColor(light) * getLightIntensity(light), 0.0); + +<@if SHOW_LIGHT_CONTOUR@> // Show edge - float maxRadius = getLightRadius(light); - float edge = abs(2.0 * ((maxRadius - fragLightDistance) / (0.1)) - 1.0); + float edge = abs(2.0 * ((getLightRadius(light) - fragLightDistance) / (0.1)) - 1.0); if (edge < 1) { float edgeCoord = exp2(-8.0*edge*edge); gl_FragColor = vec4(edgeCoord * edgeCoord * getLightColor(light), 0.0); - } else { - gl_FragColor = vec4((diffuseColor + specularColor) * lightAttenuation * getLightColor(light) * getLightIntensity(light), 0.0); } +<@endif@> } diff --git a/libraries/render-utils/src/spot_light.slf b/libraries/render-utils/src/spot_light.slf index bbe4107a4d..aec1ce4b89 100644 --- a/libraries/render-utils/src/spot_light.slf +++ b/libraries/render-utils/src/spot_light.slf @@ -25,9 +25,8 @@ uniform mat4 invViewMat; void main(void) { - // get the depth and exit early if it doesn't pass the test + // Grab the fragment data from the uv vec2 texCoord = gl_TexCoord[0].st / gl_TexCoord[0].q; - DeferredFragment frag = unpackDeferredFragment(texCoord); // Kill if in front of the light volume @@ -40,8 +39,8 @@ void main(void) { Light light = getLight(); // Make the Light vector going from fragment to light center in world space - vec4 wPos = invViewMat * frag.position; - vec3 fragLightVec = getLightPosition(light) - wPos.xyz; + vec4 fragPos = invViewMat * frag.position; + vec3 fragLightVec = getLightPosition(light) - fragPos.xyz; // Kill if too far from the light center if (dot(fragLightVec, fragLightVec) > getLightSquareRadius(light)) { @@ -50,7 +49,6 @@ void main(void) { // Allright we re valid in the volume float fragLightDistance = length(fragLightVec); - float lightAttenuation = evalLightAttenuation(light, fragLightDistance); vec3 fragLightDir = fragLightVec / fragLightDistance; // Kill if not in the spot light (ah ah !) @@ -60,38 +58,30 @@ void main(void) { discard; } + // Eval shading vec3 fragNormal = vec3(invViewMat * vec4(frag.normal, 0.0)); vec4 fragEyeVector = invViewMat * vec4(-frag.position.xyz, 0.0); vec3 fragEyeDir = normalize(fragEyeVector.xyz); - vec4 shading = evalFragShading(fragNormal, fragLightDir, fragEyeDir, frag.specular, frag.gloss); + + // Eval attenuation + float radialAttenuation = evalLightAttenuation(light, fragLightDistance); + float angularAttenuation = evalLightSpotAttenuation(light, cosSpotAngle); + // Final Lighting color vec3 fragColor = shading.w * (frag.diffuse + shading.xyz); - /* vec3 wHalfDir = normalize(fragEyeDir + fragLightDir); + gl_FragColor = vec4(fragColor * angularAttenuation * radialAttenuation * getLightColor(light) * getLightIntensity(light), 0.0); - // Diffuse Lighting - float diffuseDot = dot(wNor.xyz, fragLightDir); - float facingLight = step(0.0, diffuseDot); - vec3 diffuseColor = frag.diffuse * diffuseDot * facingLight; - - // compute the specular multiplier (sans exponent) - float specularPower = facingLight * max(0.0, dot(fragEyeDir, wHalfDir)); - vec3 specularColor = pow(specularPower, frag.gloss * 128.0) * frag.specular; - */ - // Eval angular attenuation - float lightAngularAttenuation = clamp((cosSpotAngle - getLightSpotAngleCos(light)) / (1.0 - getLightSpotAngleCos(light)), 0.0, 1.0); - - // Show edge - float maxRadius = getLightRadius(light); - float edge = abs(2.0 * ((maxRadius - fragLightDistance) / (0.1)) - 1.0); - if (cosSpotAngle < 1.01 * getLightSpotAngleCos(light)) { - edge = 0; - } +<@if SHOW_LIGHT_CONTOUR@> + // Show edges + float edgeDistR = (getLightRadius(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); if (edge < 1) { float edgeCoord = exp2(-8.0*edge*edge); gl_FragColor = vec4(edgeCoord * edgeCoord * getLightColor(light), 0.0); - } else { - gl_FragColor = vec4(fragColor * lightAngularAttenuation * lightAttenuation * getLightColor(light) * getLightIntensity(light), 0.0); } +<@endif@> }