FInally getting the angular attenuation

This commit is contained in:
Sam Gateau 2015-02-04 17:24:23 -08:00
parent 6c00f29f2b
commit 8e1eebbbd4
6 changed files with 54 additions and 88 deletions

View file

@ -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;
}

View file

@ -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>(); }
Schema& editSchema() { return _schemaBuffer.edit<Schema>(); }

View file

@ -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);

View file

@ -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) {

View file

@ -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@>
}

View file

@ -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@>
}