mirror of
https://github.com/overte-org/overte.git
synced 2025-05-29 07:01:07 +02:00
improving on the poin light attenuatiion formula
This commit is contained in:
parent
b9bbd7745f
commit
b6836af071
6 changed files with 64 additions and 44 deletions
|
@ -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) {
|
||||
|
|
|
@ -74,8 +74,8 @@ public:
|
|||
|
||||
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)
|
||||
{}
|
||||
|
|
|
@ -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<GeometryCache>();
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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@>
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
// 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;
|
||||
|
@ -32,18 +34,25 @@ void main(void) {
|
|||
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);
|
||||
vec4 wPos;
|
||||
wPos = invViewMat * frag.position;
|
||||
Light light = getLight();
|
||||
gl_FragColor = vec4(frag.normal, 0.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));
|
||||
vec3 lightVector = getLightPosition(light) - wPos.xyz;
|
||||
if (dot(lightVector, lightVector) > getLightSquareRadius(light)) {
|
||||
discard;
|
||||
}
|
||||
|
||||
// compute the base color based on OpenGL lighting model
|
||||
vec4 lightVector = gl_LightSource[1].position - position;
|
||||
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);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue