Merge /u/fgarlin/simgear/ branch next into next
https://sourceforge.net/p/flightgear/simgear/merge-requests/68/
This commit is contained in:
commit
c2f2f25046
@ -73,32 +73,39 @@ SGLight::appendLight(const SGPropertyNode *configNode,
|
|||||||
light->setSpotExponent(configNode->getFloatValue("spot-exponent"));
|
light->setSpotExponent(configNode->getFloatValue("spot-exponent"));
|
||||||
light->setSpotCutoff(configNode->getFloatValue("spot-cutoff"));
|
light->setSpotCutoff(configNode->getFloatValue("spot-cutoff"));
|
||||||
|
|
||||||
osg::Group *group = 0;
|
|
||||||
if ((p = configNode->getNode("offsets")) == NULL) {
|
|
||||||
group = new osg::Group;
|
|
||||||
} else {
|
|
||||||
// Set up the alignment node ("stolen" from animation.cxx)
|
|
||||||
// XXX Order of rotations is probably not correct.
|
|
||||||
osg::MatrixTransform *align = new osg::MatrixTransform;
|
osg::MatrixTransform *align = new osg::MatrixTransform;
|
||||||
osg::Matrix res_matrix;
|
align->addChild(light);
|
||||||
res_matrix.makeRotate(
|
|
||||||
p->getFloatValue("pitch-deg", 0.0)*SG_DEGREES_TO_RADIANS,
|
osg::Matrix t;
|
||||||
|
osg::Vec3 pos(configNode->getFloatValue("position/x-m"),
|
||||||
|
configNode->getFloatValue("position/y-m"),
|
||||||
|
configNode->getFloatValue("position/z-m"));
|
||||||
|
t.makeTranslate(pos);
|
||||||
|
|
||||||
|
osg::Matrix r;
|
||||||
|
if (const SGPropertyNode *dirNode = configNode->getNode("direction")) {
|
||||||
|
if (dirNode->hasValue("pitch-deg")) {
|
||||||
|
r.makeRotate(
|
||||||
|
dirNode->getFloatValue("pitch-deg")*SG_DEGREES_TO_RADIANS,
|
||||||
osg::Vec3(0, 1, 0),
|
osg::Vec3(0, 1, 0),
|
||||||
p->getFloatValue("roll-deg", 0.0)*SG_DEGREES_TO_RADIANS,
|
dirNode->getFloatValue("roll-deg")*SG_DEGREES_TO_RADIANS,
|
||||||
osg::Vec3(1, 0, 0),
|
osg::Vec3(1, 0, 0),
|
||||||
p->getFloatValue("heading-deg", 0.0)*SG_DEGREES_TO_RADIANS,
|
dirNode->getFloatValue("heading-deg")*SG_DEGREES_TO_RADIANS,
|
||||||
osg::Vec3(0, 0, 1));
|
osg::Vec3(0, 0, 1));
|
||||||
|
} else if (dirNode->hasValue("lookat-x-m")) {
|
||||||
osg::Matrix tmat;
|
osg::Vec3 lookAt(dirNode->getFloatValue("lookat-x-m"),
|
||||||
tmat.makeTranslate(configNode->getFloatValue("offsets/x-m", 0.0),
|
dirNode->getFloatValue("lookat-y-m"),
|
||||||
configNode->getFloatValue("offsets/y-m", 0.0),
|
dirNode->getFloatValue("lookat-z-m"));
|
||||||
configNode->getFloatValue("offsets/z-m", 0.0));
|
osg::Vec3 dir = lookAt - pos;
|
||||||
|
r.makeRotate(osg::Vec3(0, 0, -1), dir);
|
||||||
align->setMatrix(res_matrix * tmat);
|
} else {
|
||||||
group = align;
|
r.makeRotate(osg::Vec3(0, 0, -1),
|
||||||
|
osg::Vec3(dirNode->getFloatValue("x"),
|
||||||
|
dirNode->getFloatValue("y"),
|
||||||
|
dirNode->getFloatValue("z")));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
group->addChild(light);
|
align->setMatrix(r * t);
|
||||||
|
|
||||||
osg::Shape *debug_shape;
|
osg::Shape *debug_shape;
|
||||||
if (light->getType() == SGLight::Type::POINT) {
|
if (light->getType() == SGLight::Type::POINT) {
|
||||||
@ -125,14 +132,14 @@ SGLight::appendLight(const SGPropertyNode *configNode,
|
|||||||
debug_switch->addChild(debug_geode);
|
debug_switch->addChild(debug_geode);
|
||||||
simgear::getPropertyRoot()->getNode("/sim/debug/show-light-volumes", true)->
|
simgear::getPropertyRoot()->getNode("/sim/debug/show-light-volumes", true)->
|
||||||
addChangeListener(new SGLightDebugListener(debug_switch), true);
|
addChangeListener(new SGLightDebugListener(debug_switch), true);
|
||||||
group->addChild(debug_switch);
|
align->addChild(debug_switch);
|
||||||
|
|
||||||
if ((p = configNode->getNode("name")) != NULL)
|
if ((p = configNode->getNode("name")) != NULL)
|
||||||
group->setName(p->getStringValue());
|
align->setName(p->getStringValue());
|
||||||
else
|
else
|
||||||
group->setName("light");
|
align->setName("light");
|
||||||
|
|
||||||
return group;
|
return align;
|
||||||
}
|
}
|
||||||
|
|
||||||
SGLight::SGLight() :
|
SGLight::SGLight() :
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
|
|
||||||
#include <osg/io_utils>
|
#include <osg/io_utils>
|
||||||
|
|
||||||
|
#include <simgear/constants.h>
|
||||||
#include <simgear/structure/exception.hxx>
|
#include <simgear/structure/exception.hxx>
|
||||||
|
|
||||||
namespace simgear {
|
namespace simgear {
|
||||||
@ -40,7 +41,7 @@ const int MAX_SPOTLIGHTS = 256;
|
|||||||
// It must be a multiple of the size of a vec4 as per the std140 layout rules.
|
// It must be a multiple of the size of a vec4 as per the std140 layout rules.
|
||||||
// See https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_uniform_buffer_object.txt
|
// See https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_uniform_buffer_object.txt
|
||||||
const int POINTLIGHT_BLOCK_SIZE = 20;
|
const int POINTLIGHT_BLOCK_SIZE = 20;
|
||||||
const int SPOTLIGHT_BLOCK_SIZE = 8;
|
const int SPOTLIGHT_BLOCK_SIZE = 28;
|
||||||
|
|
||||||
ClusteredShading::ClusteredShading(osg::Camera *camera,
|
ClusteredShading::ClusteredShading(osg::Camera *camera,
|
||||||
const SGPropertyNode *config) :
|
const SGPropertyNode *config) :
|
||||||
@ -180,12 +181,38 @@ ClusteredShading::update(const SGLightList &light_list)
|
|||||||
PointlightBound point;
|
PointlightBound point;
|
||||||
point.light = light;
|
point.light = light;
|
||||||
point.position = osg::Vec4f(0.0f, 0.0f, 0.0f, 1.0f) *
|
point.position = osg::Vec4f(0.0f, 0.0f, 0.0f, 1.0f) *
|
||||||
osg::computeLocalToWorld(light->getParentalNodePaths()[0]) *
|
// The parenthesis are very important: if the vector is
|
||||||
_camera->getViewMatrix();
|
// multiplied by the local to world matrix first we'll have
|
||||||
|
// precision issues
|
||||||
|
(osg::computeLocalToWorld(light->getParentalNodePaths()[0]) *
|
||||||
|
_camera->getViewMatrix());
|
||||||
point.range = light->getRange();
|
point.range = light->getRange();
|
||||||
|
|
||||||
_point_bounds.push_back(point);
|
_point_bounds.push_back(point);
|
||||||
} else if (light->getType() == SGLight::Type::SPOT) {
|
} else if (light->getType() == SGLight::Type::SPOT) {
|
||||||
|
SpotlightBound spot;
|
||||||
|
spot.light = light;
|
||||||
|
spot.position = osg::Vec4f(0.0f, 0.0f, 0.0f, 1.0f) *
|
||||||
|
(osg::computeLocalToWorld(light->getParentalNodePaths()[0]) *
|
||||||
|
_camera->getViewMatrix());
|
||||||
|
spot.direction = osg::Vec4f(0.0f, 0.0f, -1.0f, 0.0f) *
|
||||||
|
(osg::computeLocalToWorld(light->getParentalNodePaths()[0]) *
|
||||||
|
_camera->getViewMatrix());
|
||||||
|
|
||||||
|
float range = light->getRange();
|
||||||
|
float angle = light->getSpotCutoff() * SG_DEGREES_TO_RADIANS;
|
||||||
|
spot.cos_cutoff = cos(angle);
|
||||||
|
if(angle > SGD_PI_4) {
|
||||||
|
spot.bounding_sphere.radius = range * tan(angle);
|
||||||
|
} else {
|
||||||
|
spot.bounding_sphere.radius =
|
||||||
|
range * 0.5f / pow(spot.cos_cutoff, 2.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
spot.bounding_sphere.center =
|
||||||
|
spot.position + spot.direction * spot.bounding_sphere.radius;
|
||||||
|
|
||||||
|
_spot_bounds.push_back(spot);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (_point_bounds.size() > MAX_POINTLIGHTS ||
|
if (_point_bounds.size() > MAX_POINTLIGHTS ||
|
||||||
@ -265,8 +292,9 @@ ClusteredShading::update(const SGLightList &light_list)
|
|||||||
_light_grid->dirty();
|
_light_grid->dirty();
|
||||||
_light_indices->dirty();
|
_light_indices->dirty();
|
||||||
|
|
||||||
// Upload pointlight data
|
// Upload pointlight and spotlight data
|
||||||
writePointlightData();
|
writePointlightData();
|
||||||
|
writeSpotlightData();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -301,6 +329,7 @@ ClusteredShading::assignLightsToSlice(int slice)
|
|||||||
GLuint local_point_count = 0;
|
GLuint local_point_count = 0;
|
||||||
GLuint local_spot_count = 0;
|
GLuint local_spot_count = 0;
|
||||||
|
|
||||||
|
// Test point lights
|
||||||
for (GLushort point_iterator = 0;
|
for (GLushort point_iterator = 0;
|
||||||
point_iterator < _point_bounds.size();
|
point_iterator < _point_bounds.size();
|
||||||
++point_iterator) {
|
++point_iterator) {
|
||||||
@ -328,25 +357,40 @@ ClusteredShading::assignLightsToSlice(int slice)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test spot lights
|
||||||
|
for (GLushort spot_iterator = 0;
|
||||||
|
spot_iterator < _spot_bounds.size();
|
||||||
|
++spot_iterator) {
|
||||||
|
SpotlightBound spot = _spot_bounds[spot_iterator];
|
||||||
|
|
||||||
|
// Perform frustum-sphere collision tests
|
||||||
|
float distance = 0.0f;
|
||||||
|
for (int j = 0; j < 6; j++) {
|
||||||
|
distance = subfrustum.plane[j] * spot.bounding_sphere.center
|
||||||
|
+ spot.bounding_sphere.radius;
|
||||||
|
if (distance <= 0.0f)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (distance > 0.0f) {
|
||||||
|
// Update light index list
|
||||||
|
indices[_global_light_count] = spot_iterator;
|
||||||
|
++local_spot_count;
|
||||||
|
++_global_light_count; // Atomic increment
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_global_light_count >= MAX_LIGHT_INDICES) {
|
||||||
|
throw sg_range_exception(
|
||||||
|
"Clustered shading light index count is over the hardcoded limit ("
|
||||||
|
+ std::to_string(MAX_LIGHT_INDICES) + ")");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Update light grid
|
// Update light grid
|
||||||
grid[(z_offset + i) * 3 + 0] = start_offset;
|
grid[(z_offset + i) * 3 + 0] = start_offset;
|
||||||
grid[(z_offset + i) * 3 + 1] = local_point_count;
|
grid[(z_offset + i) * 3 + 1] = local_point_count;
|
||||||
grid[(z_offset + i) * 3 + 2] = local_spot_count;
|
grid[(z_offset + i) * 3 + 2] = local_spot_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
// for (int y = 0; y < _n_vtiles; ++y) {
|
|
||||||
// for (int x = 0; x < _n_htiles; ++x) {
|
|
||||||
// std::cout << grid[(y * _n_htiles + x) * 3 + 0] << ","
|
|
||||||
// << grid[(y * _n_htiles + x) * 3 + 1] << " ";
|
|
||||||
// }
|
|
||||||
// std::cout << std::endl;
|
|
||||||
// }
|
|
||||||
// std::cout << "\n\n";
|
|
||||||
|
|
||||||
// for (int i = 0; i < n_vtiles * n_htiles; ++i) {
|
|
||||||
// std::cout << indices[i] << " ";
|
|
||||||
// }
|
|
||||||
// std::cout << "\n";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -385,6 +429,51 @@ ClusteredShading::writePointlightData()
|
|||||||
_pointlight_data->dirty();
|
_pointlight_data->dirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ClusteredShading::writeSpotlightData()
|
||||||
|
{
|
||||||
|
GLfloat *data = reinterpret_cast<GLfloat *>(&(*_spotlight_data)[0]);
|
||||||
|
|
||||||
|
for (const auto &spot : _spot_bounds) {
|
||||||
|
// vec4 position
|
||||||
|
*data++ = spot.position.x();
|
||||||
|
*data++ = spot.position.y();
|
||||||
|
*data++ = spot.position.z();
|
||||||
|
*data++ = 1.0f;
|
||||||
|
// vec4 direction
|
||||||
|
*data++ = spot.direction.x();
|
||||||
|
*data++ = spot.direction.y();
|
||||||
|
*data++ = spot.direction.z();
|
||||||
|
*data++ = 0.0f;
|
||||||
|
// vec4 ambient
|
||||||
|
*data++ = spot.light->getAmbient().x();
|
||||||
|
*data++ = spot.light->getAmbient().y();
|
||||||
|
*data++ = spot.light->getAmbient().z();
|
||||||
|
*data++ = spot.light->getAmbient().w();
|
||||||
|
// vec4 diffuse
|
||||||
|
*data++ = spot.light->getDiffuse().x();
|
||||||
|
*data++ = spot.light->getDiffuse().y();
|
||||||
|
*data++ = spot.light->getDiffuse().z();
|
||||||
|
*data++ = spot.light->getDiffuse().w();
|
||||||
|
// vec4 specular
|
||||||
|
*data++ = spot.light->getSpecular().x();
|
||||||
|
*data++ = spot.light->getSpecular().y();
|
||||||
|
*data++ = spot.light->getSpecular().z();
|
||||||
|
*data++ = spot.light->getSpecular().w();
|
||||||
|
// vec4 attenuation (x = constant, y = linear, z = quadratic, w = range)
|
||||||
|
*data++ = spot.light->getConstantAttenuation();
|
||||||
|
*data++ = spot.light->getLinearAttenuation();
|
||||||
|
*data++ = spot.light->getQuadraticAttenuation();
|
||||||
|
*data++ = spot.light->getRange();
|
||||||
|
// float cos_cutoff
|
||||||
|
*data++ = spot.cos_cutoff;
|
||||||
|
// float exponent
|
||||||
|
*data++ = spot.light->getSpotExponent();
|
||||||
|
// Needs 2N padding (8 bytes)
|
||||||
|
}
|
||||||
|
_spotlight_data->dirty();
|
||||||
|
}
|
||||||
|
|
||||||
float
|
float
|
||||||
ClusteredShading::getDepthForSlice(int slice) const
|
ClusteredShading::getDepthForSlice(int slice) const
|
||||||
{
|
{
|
||||||
|
@ -42,19 +42,25 @@ protected:
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct PointlightBound {
|
struct PointlightBound {
|
||||||
SGLight *light;
|
SGLight *light = nullptr;
|
||||||
osg::Vec4f position;
|
osg::Vec4f position;
|
||||||
float range;
|
float range = 0.0f;
|
||||||
};
|
};
|
||||||
struct SpotlightBound {
|
struct SpotlightBound {
|
||||||
SGLight *light;
|
SGLight *light = nullptr;
|
||||||
osg::Vec4f position;
|
osg::Vec4f position;
|
||||||
float range;
|
osg::Vec4f direction;
|
||||||
|
float cos_cutoff = 0.0f;
|
||||||
|
struct {
|
||||||
|
osg::Vec4f center;
|
||||||
|
float radius = 0.0f;
|
||||||
|
} bounding_sphere;
|
||||||
};
|
};
|
||||||
|
|
||||||
void threadFunc(int thread_id);
|
void threadFunc(int thread_id);
|
||||||
void assignLightsToSlice(int slice);
|
void assignLightsToSlice(int slice);
|
||||||
void writePointlightData();
|
void writePointlightData();
|
||||||
|
void writeSpotlightData();
|
||||||
float getDepthForSlice(int slice) const;
|
float getDepthForSlice(int slice) const;
|
||||||
|
|
||||||
osg::observer_ptr<osg::Camera> _camera;
|
osg::observer_ptr<osg::Camera> _camera;
|
||||||
|
@ -567,8 +567,7 @@ struct ShadowMapPassBuilder : public PassBuilder {
|
|||||||
|
|
||||||
osg::Camera *camera = pass->camera;
|
osg::Camera *camera = pass->camera;
|
||||||
camera->setReferenceFrame(osg::Camera::ABSOLUTE_RF_INHERIT_VIEWPOINT);
|
camera->setReferenceFrame(osg::Camera::ABSOLUTE_RF_INHERIT_VIEWPOINT);
|
||||||
camera->setCullingMode(camera->getCullingMode() &
|
camera->setCullingMode(osg::CullSettings::ENABLE_ALL_CULLING);
|
||||||
~osg::CullSettings::SMALL_FEATURE_CULLING);
|
|
||||||
//camera->setComputeNearFarMode(
|
//camera->setComputeNearFarMode(
|
||||||
// osg::CullSettings::COMPUTE_NEAR_FAR_USING_BOUNDING_VOLUMES);
|
// osg::CullSettings::COMPUTE_NEAR_FAR_USING_BOUNDING_VOLUMES);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user