diff --git a/libraries/model/src/model/Light.cpp b/libraries/model/src/model/Light.cpp index ea62a564d5..201144622f 100755 --- a/libraries/model/src/model/Light.cpp +++ b/libraries/model/src/model/Light.cpp @@ -40,25 +40,19 @@ Light::~Light() { void Light::setPosition(const Vec3& position) { _transform.setTranslation(position); - _transform.getMatrix(editSchema()._transform); + editSchema()._position = Vec4(position, 1.f); } void Light::setOrientation(const glm::quat& orientation) { _transform.setRotation(orientation); - _transform.getMatrix(editSchema()._transform); } void Light::setDirection(const Vec3& direction) { - glm::mat3 rotation( - Vec3(1.0f, 0.0f, 0.0f), - Vec3(0.0f, 1.0f, 0.0f), - -direction); - - setOrientation(glm::quat(rotation)); + editSchema()._direction = Vec4(direction, 0.f); } const Vec3& Light::getDirection() const { - return Vec3(_transform.transform(Vec4(0.0f, 0.0f, 1.0f, 0.0f))); + return Vec3(getSchema()._direction); } void Light::setColor(const Color& color) { @@ -69,11 +63,13 @@ void Light::setIntensity(float intensity) { editSchema()._intensity = intensity; } -void Light::setAttenuationRadius(float radius) { +void Light::setMaximumRadius(float radius) { if (radius <= 0.f) { radius = 1.0f; } - editSchema()._attenuation = Vec4(1.0f, 2.0f/radius, 1.0f/(radius*radius), radius); + float CutOffIntensityRatio = 0.01f; + float surfaceRadius = radius / (sqrt(1.0f / CutOffIntensityRatio) - 1.f); + editSchema()._attenuation = Vec4(surfaceRadius, 1.0f/surfaceRadius, CutOffIntensityRatio, radius); } void Light::setSpotCone(float angle) { diff --git a/libraries/model/src/model/Light.h b/libraries/model/src/model/Light.h index f731255f8e..107d30fb5e 100755 --- a/libraries/model/src/model/Light.h +++ b/libraries/model/src/model/Light.h @@ -73,9 +73,9 @@ public: void setIntensity(float intensity); bool isRanged() const { return (getType() == POINT) || (getType() == SPOT ); } - - void setAttenuationRadius(float radius); - float getAttenuationRadius() const { return getSchema()._attenuation.w; } + + void setMaximumRadius(float radius); + float getMaximumRadius() const { return getSchema()._attenuation.w; } // Spot properties bool isSpot() const { return getType() == SPOT; } @@ -87,7 +87,8 @@ public: // Schema to access the attribute values of the light class Schema { public: - glm::mat4 _transform; + Vec4 _position; + Vec4 _direction; Color _color; float _intensity; Vec4 _attenuation; @@ -97,10 +98,11 @@ public: Vec4 _control; Schema() : - _transform(), + _position(0.0f, 0.0f, 0.0f, 1.0f), + _direction(0.0f, 0.0f, -1.0f, 0.f), _color(1.0f), _intensity(1.0f), - _attenuation(1.0f, 2.0f, 1.0f, 1.0f), + _attenuation(1.0f, 1.0f, 1.0f, 1.0f), _spot(0.0f, 0.0f, 0.0f, 0.0f), _control(0.0f) {} diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index 58e90f57d1..6899a47c99 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -275,7 +275,7 @@ void DeferredLightingEffect::addSpotLight(const glm::vec3& position, float radiu model::LightPointer lp = model::LightPointer(new model::Light()); lp->setPosition(position); - lp->setAttenuationRadius(radius); + lp->setMaximumRadius(radius); lp->setColor(diffuse); lp->setIntensity(1.0f); lp->setType(model::Light::POINT); @@ -297,7 +297,7 @@ void DeferredLightingEffect::addSpotLight(const glm::vec3& position, float radiu model::LightPointer ls = model::LightPointer(new model::Light()); ls->setPosition(position); ls->setDirection(direction); - ls->setAttenuationRadius(radius); + ls->setMaximumRadius(radius); ls->setSpotCone(cutoff); ls->setColor(diffuse); ls->setIntensity(1.0f); @@ -453,6 +453,8 @@ void DeferredLightingEffect::render() { const glm::vec3& eyePoint = _viewState->getCurrentViewFrustum()->getPosition(); float nearRadius = glm::distance(eyePoint, _viewState->getCurrentViewFrustum()->getNearTopLeft()); + glm::mat4 invViewMat; + _viewState->getViewTransform().getMatrix(invViewMat); auto geometryCache = DependencyManager::get(); @@ -470,7 +472,9 @@ void DeferredLightingEffect::render() { batch.setUniformBuffer(_pointLightLocations.lightBufferUnit, light->getSchemaBuffer()); gpu::GLBackend::renderBatch(batch); } - _spotLight.setUniformValue(_pointLightLocations.radius, light->getAttenuationRadius()); + glUniformMatrix4fv(_pointLightLocations.invViewMat, 1, false, reinterpret_cast< const GLfloat* >(&invViewMat)); + // _pointLight.setUniformValue(_pointLightLocations.viewMat, reinterpret_cast< const GLfloat* >(&viewMat)); + // _spotLight.setUniformValue(_pointLightLocations.radius, light->getAttenuationRadius()); /* @@ -485,7 +489,7 @@ void DeferredLightingEffect::render() { */ glPushMatrix(); - float expandedRadius = light->getAttenuationRadius() * (1.0f + SCALE_EXPANSION); + float expandedRadius = light->getMaximumRadius() * (1.0f + SCALE_EXPANSION); if (glm::distance(eyePoint, glm::vec3(light->getPosition())) < expandedRadius + nearRadius) { glLoadIdentity(); glTranslatef(0.0f, 0.0f, -1.0f); @@ -525,7 +529,7 @@ void DeferredLightingEffect::render() { batch.setUniformBuffer(_spotLightLocations.lightBufferUnit, light->getSchemaBuffer()); gpu::GLBackend::renderBatch(batch); } - _spotLight.setUniformValue(_spotLightLocations.radius, light->getAttenuationRadius()); + // _spotLight.setUniformValue(_spotLightLocations.radius, light->getAttenuationRadius()); /* _spotLight.setUniformValue(_spotLightLocations.radius, light.radius); @@ -543,7 +547,7 @@ void DeferredLightingEffect::render() { glPushMatrix(); - float expandedRadius = light->getAttenuationRadius() * (1.0f + SCALE_EXPANSION); + float expandedRadius = light->getMaximumRadius() * (1.0f + SCALE_EXPANSION); float edgeRadius = expandedRadius / glm::cos(light->getSpotConeAngle()); if (glm::distance(eyePoint, glm::vec3(light->getPosition())) < edgeRadius + nearRadius) { glLoadIdentity(); @@ -563,7 +567,7 @@ void DeferredLightingEffect::render() { glm::quat spotRotation = rotationBetween(glm::vec3(0.0f, 0.0f, -1.0f), light->getDirection()); glm::vec3 axis = glm::axis(spotRotation); glRotatef(glm::degrees(glm::angle(spotRotation)), axis.x, axis.y, axis.z); - glTranslatef(0.0f, 0.0f, -light->getAttenuationRadius() * (1.0f + SCALE_EXPANSION * 0.5f)); + glTranslatef(0.0f, 0.0f, -light->getMaximumRadius() * (1.0f + SCALE_EXPANSION * 0.5f)); geometryCache->renderCone(expandedRadius * glm::tan(light->getSpotConeAngle()), expandedRadius, 32, 1); } @@ -649,6 +653,7 @@ void DeferredLightingEffect::loadLightProgram(const char* fragSource, bool limit locations.depthTexCoordScale = program.uniformLocation("depthTexCoordScale"); locations.radius = program.uniformLocation("radius"); locations.ambientSphere = program.uniformLocation("ambientSphere.L00"); + locations.invViewMat = program.uniformLocation("invViewMat"); GLint loc = -1; #if defined(Q_OS_MAC) @@ -661,8 +666,8 @@ void DeferredLightingEffect::loadLightProgram(const char* fragSource, bool limit #elif defined(Q_OS_WIN) loc = glGetUniformBlockIndex(program.programId(), "lightBuffer"); if (loc >= 0) { - glUniformBlockBinding(program.programId(), loc, 1); - locations.lightBufferUnit = 1; + glUniformBlockBinding(program.programId(), loc, 0); + locations.lightBufferUnit = 0; } else { locations.lightBufferUnit = -1; } diff --git a/libraries/render-utils/src/DeferredLightingEffect.h b/libraries/render-utils/src/DeferredLightingEffect.h index 5c39c3041e..60596dd86f 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.h +++ b/libraries/render-utils/src/DeferredLightingEffect.h @@ -105,6 +105,7 @@ private: int radius; int ambientSphere; int lightBufferUnit; + int invViewMat; }; static void loadLightProgram(const char* fragSource, bool limited, ProgramObject& program, LightLocations& locations); diff --git a/libraries/render-utils/src/Light.slh b/libraries/render-utils/src/Light.slh index e91d1d93cb..a48f7da81d 100755 --- a/libraries/render-utils/src/Light.slh +++ b/libraries/render-utils/src/Light.slh @@ -12,8 +12,8 @@ <@def LIGHT_SLH@> struct Light { - mat4 _transform; - + vec4 _position; + vec4 _direction; vec4 _color; vec4 _attenuation; vec4 _spot; @@ -23,14 +23,18 @@ struct Light { vec4 _control; }; -vec3 getLightPosition(Light l) { return l._transform[3].xyz; } -vec3 getLightDirection(Light l) { return -l._transform[2].xyz; } // direction is -Z axis +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 evalLightAttenuation(Light l, float r) { - return clamp(1.0/(l._attenuation.x + l._attenuation.y * r + l._attenuation.z * r * r), 0.0, 1.0); + float d = max(r - l._attenuation.x, 0.0); + float denom = d * l._attenuation.y + 1.0; + float attenuation = 1.0 / (denom * denom); + return max((attenuation - l._attenuation.z)/(1.0 - l._attenuation.z), 0.0); + // return clamp(1.0/(l._attenuation.x + l._attenuation.y * r + l._attenuation.z * r * r), 0.0, 1.0); } float evalLightSpotAttenuation(Light l, float cosA) { @@ -40,6 +44,9 @@ float evalLightSpotAttenuation(Light l, float cosA) { return clamp(pow(cosA / l._spot.x, l._spot.w), 0.0, 1.0); } +float getLightSquareRadius(Light l) { + return l._attenuation.w * l._attenuation.w; +} <@if GLPROFILE == PC_GL@> diff --git a/libraries/render-utils/src/point_light.slf b/libraries/render-utils/src/point_light.slf index 9d9aecda95..599d10fbdb 100644 --- a/libraries/render-utils/src/point_light.slf +++ b/libraries/render-utils/src/point_light.slf @@ -21,29 +21,38 @@ // the radius (hard cutoff) of the light effect uniform float radius; +uniform mat4 invViewMat; + void main(void) { // get the depth and exit early if it doesn't pass the test vec2 texCoord = gl_TexCoord[0].st / gl_TexCoord[0].q; DeferredFragment frag = unpackDeferredFragment(texCoord); - + float depth = frag.depthVal; if (depth < gl_FragCoord.z) { discard; } - // compute the view space position using the depth - float z = near / (depth * depthScale - 1.0); - vec4 position = vec4((depthTexCoordOffset + texCoord * depthTexCoordScale) * z, z, 1.0); - - // get the normal from the map - vec4 normal = texture2D(normalMap, texCoord); - vec4 normalizedNormal = normalize(normal * 2.0 - vec4(1.0, 1.0, 1.0, 2.0)); - - // compute the base color based on OpenGL lighting model - vec4 lightVector = gl_LightSource[1].position - position; + vec4 wPos; + wPos = invViewMat * frag.position; + Light light = getLight(); + gl_FragColor = vec4(frag.normal, 0.0); + + vec3 lightVector = getLightPosition(light) - wPos.xyz; + if (dot(lightVector, lightVector) > getLightSquareRadius(light)) { + discard; + } + float lightDistance = length(lightVector); lightVector = lightVector / lightDistance; + + float lightAttenuation = evalLightAttenuation(light, lightDistance); + gl_FragColor.xyz *= lightAttenuation; +/* + float diffuse = dot(frag.normal, lightVector); + + float diffuse = dot(normalizedNormal, lightVector); float facingLight = step(0.0, diffuse); vec4 baseColor = texture2D(diffuseMap, texCoord) * (gl_FrontLightProduct[1].ambient + @@ -59,6 +68,6 @@ void main(void) { normalizedNormal)); vec4 specularColor = texture2D(specularMap, texCoord); gl_FragColor = vec4((baseColor.rgb + pow(specular, specularColor.a * 128.0) * specularColor.rgb) * attenuation, 0.0); - - gl_FragColor = vec4(frag.normal, 0.0); + */ + // gl_FragColor = vec4(frag.normal, 0.0); }