mirror of
https://github.com/overte-org/overte.git
synced 2025-04-22 23:33:34 +02:00
REvisiting the full lighting code to optimize the perf
This commit is contained in:
parent
bb5493106f
commit
2a0e67ee2a
15 changed files with 186 additions and 168 deletions
libraries
|
@ -26,7 +26,7 @@
|
|||
#include "SoundCache.h"
|
||||
#include "AudioSRC.h"
|
||||
|
||||
int audioInjectorPtrMetaTypeId = qRegisterMetaType<AudioInjector*>();
|
||||
//int audioInjectorPtrMetaTypeId = qRegisterMetaType<AudioInjector*>();
|
||||
|
||||
AbstractAudioInterface* AudioInjector::_localAudioInterface{ nullptr };
|
||||
|
||||
|
|
|
@ -13,22 +13,19 @@
|
|||
using namespace model;
|
||||
|
||||
Light::Light() {
|
||||
// only if created from nothing shall we create the Buffer to store the properties
|
||||
Schema schema;
|
||||
_schemaBuffer = std::make_shared<gpu::Buffer>(sizeof(Schema), (const gpu::Byte*) &schema);
|
||||
updateLightRadius();
|
||||
}
|
||||
|
||||
Light::Light(const Light& light) :
|
||||
_flags(light._flags),
|
||||
_schemaBuffer(light._schemaBuffer),
|
||||
_transform(light._transform)
|
||||
{
|
||||
}
|
||||
|
||||
Light& Light::operator= (const Light& light) {
|
||||
_flags = (light._flags);
|
||||
_schemaBuffer = (light._schemaBuffer);
|
||||
_lightSchemaBuffer = (light._lightSchemaBuffer);
|
||||
_ambientSchemaBuffer = (light._ambientSchemaBuffer);
|
||||
_transform = (light._transform);
|
||||
|
||||
return (*this);
|
||||
|
@ -38,15 +35,22 @@ Light::~Light() {
|
|||
}
|
||||
|
||||
void Light::setType(Type type) {
|
||||
editSchema()._control.x = float(type);
|
||||
updateLightRadius();
|
||||
if (_type != type) {
|
||||
_type = type;
|
||||
if (type != SPOT) {
|
||||
_lightSchemaBuffer.edit().volume.spotCos = -1.f;
|
||||
} else {
|
||||
_lightSchemaBuffer.edit().volume.spotCos = _spotCos;
|
||||
}
|
||||
updateLightRadius();
|
||||
}
|
||||
updateVolumeGeometry();
|
||||
}
|
||||
|
||||
|
||||
void Light::setPosition(const Vec3& position) {
|
||||
_transform.setTranslation(position);
|
||||
editSchema()._position = Vec4(position, 1.f);
|
||||
_lightSchemaBuffer.edit().volume.position = position;
|
||||
}
|
||||
|
||||
void Light::setOrientation(const glm::quat& orientation) {
|
||||
|
@ -55,39 +59,35 @@ void Light::setOrientation(const glm::quat& orientation) {
|
|||
}
|
||||
|
||||
void Light::setDirection(const Vec3& direction) {
|
||||
editSchema()._direction = glm::normalize(direction);
|
||||
_lightSchemaBuffer.edit().volume.direction = (direction);
|
||||
}
|
||||
|
||||
const Vec3& Light::getDirection() const {
|
||||
return getSchema()._direction;
|
||||
return _lightSchemaBuffer->volume.direction;
|
||||
}
|
||||
|
||||
void Light::setColor(const Color& color) {
|
||||
editSchema()._color = color;
|
||||
_lightSchemaBuffer.edit().irradiance.color = color;
|
||||
updateLightRadius();
|
||||
}
|
||||
|
||||
void Light::setIntensity(float intensity) {
|
||||
editSchema()._intensity = intensity;
|
||||
_lightSchemaBuffer.edit().irradiance.intensity = intensity;
|
||||
updateLightRadius();
|
||||
}
|
||||
|
||||
void Light::setAmbientIntensity(float intensity) {
|
||||
editSchema()._ambientIntensity = intensity;
|
||||
}
|
||||
|
||||
void Light::setFalloffRadius(float radius) {
|
||||
if (radius <= 0.0f) {
|
||||
radius = 0.1f;
|
||||
}
|
||||
editSchema()._attenuation.x = radius;
|
||||
_lightSchemaBuffer.edit().irradiance.falloffRadius = radius;
|
||||
updateLightRadius();
|
||||
}
|
||||
void Light::setMaximumRadius(float radius) {
|
||||
if (radius <= 0.f) {
|
||||
radius = 1.0f;
|
||||
}
|
||||
editSchema()._attenuation.y = radius;
|
||||
_lightSchemaBuffer.edit().volume.radius = radius;
|
||||
updateLightRadius();
|
||||
updateVolumeGeometry();
|
||||
}
|
||||
|
@ -106,7 +106,7 @@ void Light::updateLightRadius() {
|
|||
float cutoffRadius = getFalloffRadius() * ((glm::sqrt(intensity / MIN_CUTOFF_INTENSITY) - 1) - 1);
|
||||
|
||||
// If it is less than max radius, store it to buffer to avoid extra shading
|
||||
editSchema()._attenuation.z = std::min(getMaximumRadius(), cutoffRadius);
|
||||
_lightSchemaBuffer.edit().irradiance.cutoffRadius = std::min(getMaximumRadius(), cutoffRadius);
|
||||
}
|
||||
|
||||
#include <math.h>
|
||||
|
@ -119,12 +119,13 @@ void Light::setSpotAngle(float angle) {
|
|||
if (dangle > glm::half_pi<double>()) {
|
||||
dangle = glm::half_pi<double>();
|
||||
}
|
||||
|
||||
auto cosAngle = cos(dangle);
|
||||
auto sinAngle = sin(dangle);
|
||||
editSchema()._spot.x = (float) std::abs(cosAngle);
|
||||
editSchema()._spot.y = (float) std::abs(sinAngle);
|
||||
editSchema()._spot.z = (float) angle;
|
||||
_spotCos = (float)std::abs(cosAngle);
|
||||
|
||||
if (isSpot()) {
|
||||
_lightSchemaBuffer.edit().volume.spotCos = _spotCos;
|
||||
}
|
||||
|
||||
updateVolumeGeometry();
|
||||
}
|
||||
|
@ -133,22 +134,20 @@ void Light::setSpotExponent(float exponent) {
|
|||
if (exponent <= 0.f) {
|
||||
exponent = 0.0f;
|
||||
}
|
||||
editSchema()._spot.w = exponent;
|
||||
_lightSchemaBuffer.edit().irradiance.falloffSpot = exponent;
|
||||
}
|
||||
|
||||
void Light::setShowContour(float show) {
|
||||
if (show <= 0.f) {
|
||||
show = 0.0f;
|
||||
}
|
||||
editSchema()._control.z = show;
|
||||
|
||||
void Light::setAmbientIntensity(float intensity) {
|
||||
_ambientSchemaBuffer.edit().intensity = intensity;
|
||||
}
|
||||
|
||||
void Light::setAmbientSphere(const gpu::SphericalHarmonics& sphere) {
|
||||
editSchema()._ambientSphere = sphere;
|
||||
_ambientSchemaBuffer.edit().ambientSphere = sphere;
|
||||
}
|
||||
|
||||
void Light::setAmbientSpherePreset(gpu::SphericalHarmonics::Preset preset) {
|
||||
editSchema()._ambientSphere.assignPreset(preset);
|
||||
_ambientSchemaBuffer.edit().ambientSphere.assignPreset(preset);
|
||||
}
|
||||
|
||||
void Light::setAmbientMap(gpu::TexturePointer ambientMap) {
|
||||
|
@ -161,17 +160,17 @@ void Light::setAmbientMap(gpu::TexturePointer ambientMap) {
|
|||
}
|
||||
|
||||
void Light::setAmbientMapNumMips(uint16_t numMips) {
|
||||
editSchema()._ambientMapNumMips = (float)numMips;
|
||||
_ambientSchemaBuffer.edit().mapNumMips = (float)numMips;
|
||||
}
|
||||
|
||||
void Light::updateVolumeGeometry() {
|
||||
// enlarge the scales slightly to account for tesselation
|
||||
const float SCALE_EXPANSION = 0.05f;
|
||||
/* const float SCALE_EXPANSION = 0.05f;
|
||||
glm::vec4 volumeGeometry(0.0f, 0.0f, 0.0f, getMaximumRadius() * (1.0f + SCALE_EXPANSION));
|
||||
|
||||
if (getType() == SPOT) {
|
||||
const float TANGENT_LENGTH_SCALE = 0.666f;
|
||||
volumeGeometry = glm::vec4(getSpotAngleCosSin(), TANGENT_LENGTH_SCALE * tanf(0.5f * getSpotAngle()), volumeGeometry.w);
|
||||
}
|
||||
editSchema()._volumeGeometry = volumeGeometry;
|
||||
editSchema()._volumeGeometry = volumeGeometry;*/
|
||||
}
|
||||
|
|
|
@ -31,37 +31,38 @@ class Light {
|
|||
public:
|
||||
|
||||
struct LightVolume {
|
||||
vec3 position;
|
||||
float radius;
|
||||
vec3 direction;
|
||||
float spotCos;
|
||||
vec3 position { 0.f };
|
||||
float radius { 1.0f };
|
||||
vec3 direction { 0.f, 0.f, -1.f };
|
||||
float spotCos { -1.f };
|
||||
|
||||
bool isPoint() { return bool(spotCos < 0.f); }
|
||||
bool isSpot() { return bool(spotCos >= 0.f); }
|
||||
bool isPoint() const { return bool(spotCos < 0.f); }
|
||||
bool isSpot() const { return bool(spotCos >= 0.f); }
|
||||
|
||||
vec3 getPosition() { return position; }
|
||||
float getRadius() { return radius; }
|
||||
float getRadiusSquare() { return radius * radius; }
|
||||
vec3 getDirection() { return direction; }
|
||||
vec3 getPosition() const { return position; }
|
||||
float getRadius() const { return radius; }
|
||||
float getRadiusSquare() const { return radius * radius; }
|
||||
vec3 getDirection() const { return direction; }
|
||||
|
||||
float getSpotAngleCos() { return spotCos; }
|
||||
float getSpotAngleCos() const { return spotCos; }
|
||||
vec2 getSpotAngleCosSin() const { return vec2(spotCos, sqrt(1.f - spotCos * spotCos)); }
|
||||
};
|
||||
|
||||
|
||||
struct LightIrradiance {
|
||||
vec3 color;
|
||||
float intensity;
|
||||
float falloffRadius;
|
||||
float falloffSpot;
|
||||
vec3 color { 1.f };
|
||||
float intensity { 1.f };
|
||||
float falloffRadius { 0.1f };
|
||||
float cutoffRadius { 0.1f };
|
||||
float falloffSpot { 1.f };
|
||||
float spare1;
|
||||
float spare2;
|
||||
|
||||
vec3 getColor() { return color; }
|
||||
float getIntensity() { return intensity; }
|
||||
vec3 getIrradiance() { return color * intensity; }
|
||||
float getFalloffRadius() { return falloffRadius; }
|
||||
float getFalloffRadiusSquare() { return falloffRadius * falloffRadius; }
|
||||
float getFalloffSpot() { return falloffSpot; }
|
||||
vec3 getColor() const { return color; }
|
||||
float getIntensity() const { return intensity; }
|
||||
vec3 getIrradiance() const { return color * intensity; }
|
||||
float getFalloffRadius() const { return falloffRadius; }
|
||||
float getCutoffRadius() const { return cutoffRadius; }
|
||||
float getFalloffSpot() const { return falloffSpot; }
|
||||
};
|
||||
|
||||
|
||||
|
@ -93,7 +94,7 @@ public:
|
|||
virtual ~Light();
|
||||
|
||||
void setType(Type type);
|
||||
Type getType() const { return Type((int) getSchema()._control.x); }
|
||||
Type getType() const { return _type; }
|
||||
|
||||
void setPosition(const Vec3& position);
|
||||
const Vec3& getPosition() const { return _transform.getTranslation(); }
|
||||
|
@ -104,10 +105,10 @@ public:
|
|||
void setOrientation(const Quat& orientation);
|
||||
const glm::quat& getOrientation() const { return _transform.getRotation(); }
|
||||
|
||||
const Color& getColor() const { return getSchema()._color; }
|
||||
const Color& getColor() const { return _lightSchemaBuffer->irradiance.color; }
|
||||
void setColor(const Color& color);
|
||||
|
||||
float getIntensity() const { return getSchema()._intensity; }
|
||||
float getIntensity() const { return _lightSchemaBuffer->irradiance.intensity; }
|
||||
void setIntensity(float intensity);
|
||||
|
||||
bool isRanged() const { return (getType() == POINT) || (getType() == SPOT ); }
|
||||
|
@ -116,44 +117,58 @@ public:
|
|||
// expressed in meters. It is used only to calculate the falloff curve of the light.
|
||||
// Actual rendered lights will all have surface radii approaching 0.
|
||||
void setFalloffRadius(float radius);
|
||||
float getFalloffRadius() const { return getSchema()._attenuation.x; }
|
||||
float getFalloffRadius() const { return _lightSchemaBuffer->irradiance.falloffRadius; }
|
||||
|
||||
// Maximum radius is the cutoff radius of the light energy, expressed in meters.
|
||||
// It is used to bound light entities, and *will not* affect the falloff curve of the light.
|
||||
// Setting it low will result in a noticeable cutoff.
|
||||
void setMaximumRadius(float radius);
|
||||
float getMaximumRadius() const { return getSchema()._attenuation.y; }
|
||||
float getMaximumRadius() const { return _lightSchemaBuffer->volume.radius; }
|
||||
|
||||
// Spot properties
|
||||
bool isSpot() const { return getType() == SPOT; }
|
||||
void setSpotAngle(float angle);
|
||||
float getSpotAngle() const { return getSchema()._spot.z; }
|
||||
glm::vec2 getSpotAngleCosSin() const { return glm::vec2(getSchema()._spot.x, getSchema()._spot.y); }
|
||||
float getSpotAngle() const { return acos(_lightSchemaBuffer->volume.getSpotAngleCos()); }
|
||||
glm::vec2 getSpotAngleCosSin() const { return _lightSchemaBuffer->volume.getSpotAngleCosSin(); }
|
||||
void setSpotExponent(float exponent);
|
||||
float getSpotExponent() const { return getSchema()._spot.w; }
|
||||
|
||||
// For editing purpose, show the light volume contour.
|
||||
// Set to non 0 to show it, the value is used as the intensity of the contour color
|
||||
void setShowContour(float show);
|
||||
float getShowContour() const { return getSchema()._control.z; }
|
||||
float getSpotExponent() const { return _lightSchemaBuffer->irradiance.falloffSpot; }
|
||||
|
||||
// If the light has an ambient (Indirect) component, then the Ambientintensity can be used to control its contribution to the lighting
|
||||
void setAmbientIntensity(float intensity);
|
||||
float getAmbientIntensity() const { return getSchema()._ambientIntensity; }
|
||||
float getAmbientIntensity() const { return _ambientSchemaBuffer->intensity; }
|
||||
|
||||
// Spherical Harmonics storing the Ambient lighting approximation used for the Sun typed light
|
||||
void setAmbientSphere(const gpu::SphericalHarmonics& sphere);
|
||||
const gpu::SphericalHarmonics& getAmbientSphere() const { return getSchema()._ambientSphere; }
|
||||
const gpu::SphericalHarmonics& getAmbientSphere() const { return _ambientSchemaBuffer->ambientSphere; }
|
||||
void setAmbientSpherePreset(gpu::SphericalHarmonics::Preset preset);
|
||||
|
||||
void setAmbientMap(gpu::TexturePointer ambientMap);
|
||||
gpu::TexturePointer getAmbientMap() const { return _ambientMap; }
|
||||
|
||||
void setAmbientMapNumMips(uint16_t numMips);
|
||||
uint16_t getAmbientMapNumMips() const { return (uint16_t) getSchema()._ambientMapNumMips; }
|
||||
uint16_t getAmbientMapNumMips() const { return (uint16_t) _ambientSchemaBuffer->mapNumMips; }
|
||||
|
||||
// LIght Schema
|
||||
class LightSchema {
|
||||
public:
|
||||
LightVolume volume;
|
||||
LightIrradiance irradiance;
|
||||
};
|
||||
|
||||
class AmbientSchema {
|
||||
public:
|
||||
float intensity { 0.f };
|
||||
float mapNumMips { 0.f };
|
||||
float spare1;
|
||||
float spare2;
|
||||
gpu::SphericalHarmonics ambientSphere;
|
||||
};
|
||||
|
||||
using LightSchemaBuffer = gpu::StructBuffer<LightSchema>;
|
||||
using AmbientSchemaBuffer = gpu::StructBuffer<AmbientSchema>;
|
||||
|
||||
// Schema to access the attribute values of the light
|
||||
class Schema {
|
||||
/* class Schema {
|
||||
public:
|
||||
Vec4 _position{0.0f, 0.0f, 0.0f, 1.0f};
|
||||
Vec3 _direction{0.0f, 0.0f, -1.0f};
|
||||
|
@ -172,19 +187,23 @@ public:
|
|||
|
||||
gpu::SphericalHarmonics _ambientSphere;
|
||||
};
|
||||
|
||||
const UniformBufferView& getSchemaBuffer() const { return _schemaBuffer; }
|
||||
*/
|
||||
const LightSchemaBuffer& getLightSchemaBuffer() const { return _lightSchemaBuffer; }
|
||||
const AmbientSchemaBuffer& getAmbientSchemaBuffer() const { return _ambientSchemaBuffer; }
|
||||
|
||||
protected:
|
||||
|
||||
Flags _flags{ 0 };
|
||||
UniformBufferView _schemaBuffer;
|
||||
|
||||
LightSchemaBuffer _lightSchemaBuffer;
|
||||
AmbientSchemaBuffer _ambientSchemaBuffer;
|
||||
|
||||
Transform _transform;
|
||||
|
||||
gpu::TexturePointer _ambientMap;
|
||||
|
||||
const Schema& getSchema() const { return _schemaBuffer.get<Schema>(); }
|
||||
Schema& editSchema() { return _schemaBuffer.edit<Schema>(); }
|
||||
Type _type { SUN };
|
||||
float _spotCos { -1.0f }; // stored here to be able to reset the spot angle when turning the type spot on/off
|
||||
|
||||
void updateLightRadius();
|
||||
void updateVolumeGeometry();
|
||||
|
|
|
@ -23,26 +23,6 @@ struct Light {
|
|||
LightIrradiance irradiance;
|
||||
};
|
||||
|
||||
// Light is the light source its self, d is the light's distance calculated as length(unnormalized light vector).
|
||||
float evalLightAttenuation(Light l, float d) {
|
||||
float radius = lightIrradiance_getFalloffRadius(l.irradiance);
|
||||
float cutoff = lightVolume_getRadius(l.volume);
|
||||
float denom = d / radius + 1.0;
|
||||
float attenuation = 1.0 / (denom * denom);
|
||||
|
||||
|
||||
// "Fade" the edges of light sources to make things look a bit more attractive.
|
||||
// Note: this tends to look a bit odd at lower exponents.
|
||||
attenuation *= min(1, max(0, -(d - cutoff)));
|
||||
|
||||
return attenuation;
|
||||
}
|
||||
|
||||
|
||||
float evalLightSpotAttenuation(Light l, float cosA) {
|
||||
return pow(cosA, lightIrradiance_getFalloffSpot(l.irradiance));
|
||||
}
|
||||
|
||||
bool light_isSpot(Light l) { return lightVolume_isSpot(l.volume); }
|
||||
|
||||
vec3 getLightPosition(Light l) { return lightVolume_getPosition(l.volume); }
|
||||
|
|
|
@ -14,21 +14,39 @@
|
|||
#define LightIrradianceConstRef LightIrradiance
|
||||
|
||||
struct LightIrradiance {
|
||||
vec3 color;
|
||||
float intensity;
|
||||
float falloffRadius;
|
||||
float falloffSpot;
|
||||
float spare1;
|
||||
float spare2;
|
||||
vec4 colorIntensity;
|
||||
// falloffRadius, cutoffRadius, falloffSpot, spare
|
||||
vec4 attenuation;
|
||||
};
|
||||
|
||||
|
||||
vec3 lightIrradiance_getColor(LightIrradianceConstRef li) { return li.color; }
|
||||
float lightIrradiance_getIntensity(LightIrradianceConstRef li) { return li.intensity; }
|
||||
vec3 lightIrradiance_getIrradiance(LightIrradianceConstRef li) { return li.color * li.intensity; }
|
||||
float lightIrradiance_getFalloffRadius(LightIrradianceConstRef li) { return li.falloffRadius; }
|
||||
float lightIrradiance_getFalloffRadiusSquare(LightIrradianceConstRef li) { return li.falloffRadius * li.falloffRadius; }
|
||||
float lightIrradiance_getFalloffSpot(LightIrradianceConstRef li) { return li.falloffSpot; }
|
||||
vec3 lightIrradiance_getColor(LightIrradiance li) { return li.colorIntensity.xyz; }
|
||||
float lightIrradiance_getIntensity(LightIrradiance li) { return li.colorIntensity.w; }
|
||||
vec3 lightIrradiance_getIrradiance(LightIrradiance li) { return li.colorIntensity.xyz * li.colorIntensity.w; }
|
||||
float lightIrradiance_getFalloffRadius(LightIrradiance li) { return li.attenuation.x; }
|
||||
float lightIrradiance_getCutoffRadius(LightIrradiance li) { return li.attenuation.y; }
|
||||
float lightIrradiance_getFalloffSpot(LightIrradiance li) { return li.attenuation.z; }
|
||||
|
||||
|
||||
// Light is the light source its self, d is the light's distance calculated as length(unnormalized light vector).
|
||||
float lightIrradiance_evalLightAttenuation(LightIrradiance li, float d) {
|
||||
float radius = lightIrradiance_getFalloffRadius(li);
|
||||
float cutoff = lightIrradiance_getCutoffRadius(li);
|
||||
float denom = d / radius + 1.0;
|
||||
float attenuation = 1.0 / (denom * denom);
|
||||
|
||||
|
||||
// "Fade" the edges of light sources to make things look a bit more attractive.
|
||||
// Note: this tends to look a bit odd at lower exponents.
|
||||
attenuation *= min(1, max(0, -(d - cutoff)));
|
||||
|
||||
return attenuation;
|
||||
}
|
||||
|
||||
|
||||
float lightIrradiance_evalLightSpotAttenuation(LightIrradiance li, float cosA) {
|
||||
return pow(cosA, lightIrradiance_getFalloffSpot(li));
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -16,37 +16,33 @@
|
|||
#define LightVolumeConstRef LightVolume
|
||||
|
||||
struct LightVolume {
|
||||
vec3 position;
|
||||
float radius;
|
||||
vec3 direction;
|
||||
float spotCos;
|
||||
vec4 positionRadius;
|
||||
vec4 directionSpotCos;
|
||||
};
|
||||
|
||||
bool lightVolume_isPoint(LightVolumeConstRef lv) { return bool(lv.spotCos < 0.f); }
|
||||
bool lightVolume_isSpot(LightVolumeConstRef lv) { return bool(lv.spotCos >= 0.f); }
|
||||
bool lightVolume_isPoint(LightVolume lv) { return bool(lv.directionSpotCos.w < 0.f); }
|
||||
bool lightVolume_isSpot(LightVolume lv) { return bool(lv.directionSpotCos.w >= 0.f); }
|
||||
|
||||
vec3 lightVolume_getPosition(LightVolumeConstRef lv) { return lv.position; }
|
||||
float lightVolume_getRadius(LightVolumeConstRef lv) { return lv.radius; }
|
||||
float lightVolume_getRadiusSquare(LightVolumeConstRef lv) { return lv.radius * lv.radius; }
|
||||
vec3 lightVolume_getDirection(LightVolumeConstRef lv) { return lv.direction; } // direction is -Z axis
|
||||
vec3 lightVolume_getPosition(LightVolume lv) { return lv.positionRadius.xyz; }
|
||||
float lightVolume_getRadius(LightVolume lv) { return lv.positionRadius.w; }
|
||||
float lightVolume_getRadiusSquare(LightVolume lv) { return lv.positionRadius.w * lv.positionRadius.w; }
|
||||
vec3 lightVolume_getDirection(LightVolume lv) { return lv.directionSpotCos.xyz; } // direction is -Z axis
|
||||
|
||||
float lightVolume_getSpotAngleCos(LightVolumeConstRef lv) { return lv.spotCos; }
|
||||
vec2 lightVolume_getSpotOutsideNormal2(LightVolumeConstRef lv) { return vec2(-sqrt(1.0 - lv.spotCos * lv.spotCos), lv.spotCos); }
|
||||
float lightVolume_getSpotAngleCos(LightVolume lv) { return lv.directionSpotCos.w; }
|
||||
vec2 lightVolume_getSpotOutsideNormal2(LightVolume lv) { return vec2(-sqrt(1.0 - lv.directionSpotCos.w * lv.directionSpotCos.w), lv.directionSpotCos.w); }
|
||||
|
||||
|
||||
bool lightVolume_clipFragToLightVolumePoint(LightVolume lv, vec3 fragPos, vec4 fragLightVecLen2) {
|
||||
fragLightVecLen2 = vec4(lightVolume_getPosition(lv) - fragPos.xyz, 1.0f);
|
||||
bool lightVolume_clipFragToLightVolumePoint(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2) {
|
||||
fragLightVecLen2.xyz = lightVolume_getPosition(lv) - fragPos.xyz;
|
||||
fragLightVecLen2.w = dot(fragLightVecLen2.xyz, fragLightVecLen2.xyz);
|
||||
|
||||
// Kill if too far from the light center
|
||||
if (fragLightVecLen2.w > lightVolume_getRadiusSquare(lv)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
return (fragLightVecLen2.w <= lightVolume_getRadiusSquare(lv));
|
||||
}
|
||||
|
||||
bool lightVolume_clipFragToLightVolumeSpot(LightVolume lv, vec3 fragPos, vec4 fragLightVecLen2, vec4 fragLightDirLen, float cosSpotAngle) {
|
||||
fragLightVecLen2 = vec4(lightVolume_getPosition(lv) - fragPos.xyz, 1.0f);
|
||||
|
||||
bool lightVolume_clipFragToLightVolumeSpot(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2, out vec4 fragLightDirLen, out float cosSpotAngle) {
|
||||
fragLightVecLen2.xyz = lightVolume_getPosition(lv) - fragPos.xyz;
|
||||
fragLightVecLen2.w = dot(fragLightVecLen2.xyz, fragLightVecLen2.xyz);
|
||||
|
||||
// Kill if too far from the light center
|
||||
|
@ -67,6 +63,16 @@ bool lightVolume_clipFragToLightVolumeSpot(LightVolume lv, vec3 fragPos, vec4 fr
|
|||
return true;
|
||||
}
|
||||
|
||||
bool lightVolume_clipFragToLightVolumeSpotSide(LightVolume lv, vec4 fragLightVecLen2, out vec4 fragLightDirLen, out float cosSpotAngle) {
|
||||
// Allright we re valid in the volume
|
||||
fragLightDirLen.w = length(fragLightVecLen2.xyz);
|
||||
fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;
|
||||
|
||||
// Kill if not in the spot light (ah ah !)
|
||||
cosSpotAngle = max(-dot(fragLightDirLen.xyz, lightVolume_getDirection(lv)), 0.0);
|
||||
return (cosSpotAngle >= lightVolume_getSpotAngleCos(lv));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
|
|
@ -187,7 +187,7 @@ void DeferredLightingEffect::setupKeyLightBatch(gpu::Batch& batch, int lightBuff
|
|||
auto keyLight = _allocatedLights[_globalLights.front()];
|
||||
|
||||
if (lightBufferUnit >= 0) {
|
||||
batch.setUniformBuffer(lightBufferUnit, keyLight->getSchemaBuffer());
|
||||
batch.setUniformBuffer(lightBufferUnit, keyLight->getLightSchemaBuffer());
|
||||
}
|
||||
|
||||
if (keyLight->getAmbientMap() && (skyboxCubemapUnit >= 0)) {
|
||||
|
@ -727,8 +727,6 @@ void RenderDeferredLocals::run(const render::SceneContextPointer& sceneContext,
|
|||
|
||||
// Bind the global list of lights and the visible lights this frame
|
||||
batch.setUniformBuffer(deferredLightingEffect->_localLightLocations->lightBufferUnit, lightClusters->_lightStage->_lightArrayBuffer);
|
||||
batch.setUniformBuffer(deferredLightingEffect->_localLightLocations->lightIndexBufferUnit, lightClusters->_lightIndicesBuffer);
|
||||
|
||||
|
||||
batch.setUniformBuffer(LIGHT_CLUSTER_GRID_FRUSTUM_GRID_SLOT, lightClusters->_frustumGridBuffer);
|
||||
batch.setUniformBuffer(LIGHT_CLUSTER_GRID_CLUSTER_GRID_SLOT, lightClusters->_clusterGridBuffer);
|
||||
|
|
|
@ -64,9 +64,11 @@ ivec2 clusterGrid_getCluster(int index) {
|
|||
|
||||
int clusterGrid_getClusterLightId(int index, ivec2 cluster) {
|
||||
int arrayElement = cluster.y + index;
|
||||
int element = _clusterGridContent[arrayElement >> 1];
|
||||
int element = _clusterGridContent[arrayElement];
|
||||
return element;
|
||||
// int element = _clusterGridContent[arrayElement >> 1];
|
||||
|
||||
return (((arrayElement & 0x00000001) == 1) ? (element >> 16) : element) & 0x0000FFFF;
|
||||
// return (((arrayElement & 0x00000001) == 1) ? (element >> 16) : element) & 0x0000FFFF;
|
||||
}
|
||||
|
||||
<@endif@>
|
||||
|
|
|
@ -76,7 +76,7 @@ const glm::uvec4 LightClusters::MAX_GRID_DIMENSIONS { 32, 32, 31, 16384 };
|
|||
LightClusters::LightClusters() :
|
||||
_lightIndicesBuffer(std::make_shared<gpu::Buffer>()),
|
||||
_clusterGridBuffer(std::make_shared<gpu::Buffer>(), gpu::Element::INDEX_INT32),
|
||||
_clusterContentBuffer(std::make_shared<gpu::Buffer>(), gpu::Element::INDEX_UINT16) {
|
||||
_clusterContentBuffer(std::make_shared<gpu::Buffer>(), gpu::Element::INDEX_INT32) {
|
||||
auto dims = _frustumGridBuffer.edit().dims;
|
||||
_frustumGridBuffer.edit().dims = ivec3(0); // make sure we go through the full reset of the dimensionts ion the setDImensions call
|
||||
setDimensions(dims, MAX_GRID_DIMENSIONS.w);
|
||||
|
@ -109,7 +109,7 @@ void LightClusters::setDimensions(glm::uvec3 gridDims, uint32_t listBudget) {
|
|||
_clusterGridBuffer._size = _clusterGridBuffer._buffer->resize(_numClusters * sizeof(uint32_t));
|
||||
}
|
||||
|
||||
auto configListBudget = std::min(MAX_GRID_DIMENSIONS.w, listBudget) * 2;
|
||||
auto configListBudget = std::min(MAX_GRID_DIMENSIONS.w, listBudget);
|
||||
if (configListBudget != _clusterContentBuffer.getNumElements()) {
|
||||
_clusterContent.clear();
|
||||
_clusterContent.resize(configListBudget, INVALID_LIGHT);
|
||||
|
|
|
@ -94,7 +94,7 @@ public:
|
|||
const uint32_t EMPTY_CLUSTER { 0x0000FFFF };
|
||||
const LightID INVALID_LIGHT { LightStage::INVALID_INDEX };
|
||||
|
||||
using LightIndex = uint16_t;
|
||||
using LightIndex = uint32_t;
|
||||
|
||||
std::vector<uint32_t> _clusterGrid;
|
||||
std::vector<LightIndex> _clusterContent;
|
||||
|
|
|
@ -24,7 +24,7 @@ void evalLightingPoint(out vec3 diffuse, out vec3 specular, Light light,
|
|||
vec3 fragLightDir = fragLightVec / fragLightDistance;
|
||||
|
||||
// Eval attenuation
|
||||
float radialAttenuation = evalLightAttenuation(light, fragLightDistance);
|
||||
float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);
|
||||
vec3 lightEnergy = radialAttenuation * shadow * getLightIrradiance(light);
|
||||
|
||||
// Eval shading
|
||||
|
|
|
@ -23,9 +23,10 @@ void evalLightingSpot(out vec3 diffuse, out vec3 specular, Light light,
|
|||
float fragLightDistance = fragLightDirLen.w;
|
||||
vec3 fragLightDir = fragLightDirLen.xyz;
|
||||
|
||||
|
||||
// Eval attenuation
|
||||
float radialAttenuation = evalLightAttenuation(light, fragLightDistance);
|
||||
float angularAttenuation = evalLightSpotAttenuation(light, cosSpotAngle);
|
||||
float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);
|
||||
float angularAttenuation = lightIrradiance_evalLightSpotAttenuation(light.irradiance, cosSpotAngle);
|
||||
vec3 lightEnergy = angularAttenuation * radialAttenuation * shadow *getLightIrradiance(light);
|
||||
|
||||
// Eval shading
|
||||
|
|
|
@ -134,22 +134,22 @@ LightStage::LightPointer LightStage::removeLight(Index index) {
|
|||
}
|
||||
|
||||
void LightStage::updateLightArrayBuffer(Index lightId) {
|
||||
auto lightSize = sizeof(model::Light::LightSchema);
|
||||
if (!_lightArrayBuffer) {
|
||||
_lightArrayBuffer = std::make_shared<gpu::Buffer>();
|
||||
}
|
||||
|
||||
assert(checkLightId(lightId));
|
||||
auto lightSize = sizeof(model::Light::Schema);
|
||||
|
||||
if (lightId > (Index) _lightArrayBuffer->getNumTypedElements<model::Light::Schema>()) {
|
||||
if (lightId > (Index)_lightArrayBuffer->getNumTypedElements<model::Light::LightSchema>()) {
|
||||
_lightArrayBuffer->resize(lightSize * (lightId + 10));
|
||||
}
|
||||
|
||||
// lightArray is big enough so we can remap
|
||||
auto light = _lights._elements[lightId];
|
||||
if (light) {
|
||||
auto lightSchema = light->getSchemaBuffer().get<model::Light::Schema>();
|
||||
_lightArrayBuffer->setSubData<model::Light::Schema>(lightId, lightSchema);
|
||||
const auto& lightSchema = light->getLightSchemaBuffer().get();
|
||||
_lightArrayBuffer->setSubData<model::Light::LightSchema>(lightId, lightSchema);
|
||||
} else {
|
||||
// this should not happen ?
|
||||
}
|
||||
|
|
|
@ -568,7 +568,7 @@ void DebugSubsurfaceScattering::run(const render::SceneContextPointer& sceneCont
|
|||
batch.setUniformBuffer(ScatteringTask_FrameTransformSlot, frameTransform->getFrameTransformBuffer());
|
||||
batch.setUniformBuffer(ScatteringTask_ParamSlot, scatteringResource->getParametersBuffer());
|
||||
if (light) {
|
||||
batch.setUniformBuffer(ScatteringTask_LightSlot, light->getSchemaBuffer());
|
||||
batch.setUniformBuffer(ScatteringTask_LightSlot, light->getLightSchemaBuffer());
|
||||
}
|
||||
batch.setResourceTexture(ScatteringTask_ScatteringTableSlot, scatteringTable);
|
||||
batch.setResourceTexture(ScatteringTask_CurvatureMapSlot, curvatureFramebuffer->getRenderBuffer(0));
|
||||
|
|
|
@ -20,9 +20,6 @@
|
|||
// Everything about light
|
||||
<@include model/Light.slh@>
|
||||
<$declareLightBuffer(128)$>
|
||||
uniform lightIndexBuffer {
|
||||
int lightIndex[128];
|
||||
};
|
||||
<@include LightingModel.slh@>
|
||||
|
||||
|
||||
|
@ -94,33 +91,31 @@ void main(void) {
|
|||
vec4 fragEyeVector = invViewMat * vec4(-frag.position.xyz, 0.0);
|
||||
vec3 fragEyeDir = normalize(fragEyeVector.xyz);
|
||||
|
||||
|
||||
/* int theLightIndex = clusterGrid_getClusterLightId(0, cluster);
|
||||
if (theLightIndex == 65535) {
|
||||
discard;
|
||||
}
|
||||
Light light = getLight(theLightIndex);
|
||||
|
||||
int numLights = lightIndex[0];*/
|
||||
for (int i = 0; i < numLights; i++) {
|
||||
int numLightTouching = 0;
|
||||
for (int i = 0; i < numLights && numLightTouching < 16; i++) {
|
||||
// Need the light now
|
||||
int theLightIndex = clusterGrid_getClusterLightId(i, cluster);
|
||||
Light light = getLight(theLightIndex);
|
||||
|
||||
bool isSpot = light_isSpot(light);
|
||||
// Clip againgst the light volume and Make the Light vector going from fragment to light center in world space
|
||||
vec4 fragLightVecLen2;
|
||||
vec4 fragLightDirLen;
|
||||
float cosSpotAngle;
|
||||
if (isSpot) {
|
||||
if (!lightVolume_clipFragToLightVolumeSpot(light.volume, fragPos.xyz, fragLightVecLen2, fragLightDirLen, cosSpotAngle)) {
|
||||
if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragPos.xyz, fragLightVecLen2)) {
|
||||
continue;
|
||||
}
|
||||
if (isSpot && !lightVolume_clipFragToLightVolumeSpotSide(light.volume, fragLightVecLen2, fragLightDirLen, cosSpotAngle)) {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragPos.xyz, fragLightVecLen2)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (dot(frag.normal, normalize(fragLightVecLen2.xyz)) < 0.0) {
|
||||
//_fragColor.rgb += vec3(0.0, 0.0, 1.0 / 16.0);
|
||||
continue;
|
||||
}
|
||||
|
||||
numLightTouching++;
|
||||
/*
|
||||
vec3 diffuse;
|
||||
vec3 specular;
|
||||
|
||||
|
@ -135,11 +130,11 @@ void main(void) {
|
|||
frag.metallic, frag.fresnel, frag.albedo, 1.0,
|
||||
frag.scattering, midNormalCurvature, lowNormalCurvature);
|
||||
}
|
||||
|
||||
_fragColor.rgb += diffuse;
|
||||
_fragColor.rgb += specular;
|
||||
*/
|
||||
_fragColor.rgb += vec3(1.0/16.0, 0.0, 0.0);
|
||||
}
|
||||
|
||||
// _fragColor.rgb += vec3(0.05, 0.0, 0.0);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue