mirror of
https://github.com/overte-org/overte.git
synced 2025-04-22 17:53:32 +02:00
FInally getting the angular attenuation
This commit is contained in:
parent
6c00f29f2b
commit
8e1eebbbd4
6 changed files with 54 additions and 88 deletions
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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>(); }
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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@>
|
||||
}
|
||||
|
|
|
@ -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@>
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue