Preliminary changes for the HDR pipeline

- Add an Effect to stars and planets so they don't disappear when not using the fixed-pipeline.
- Allow usage of the shadow mapping related uniforms in 'quad' passes as well.
- Add extra buffer formats (some of them only work under the core profile).
- Better handling of mipmapping in the Compositor.
This commit is contained in:
Fernando García Liñán 2021-04-15 11:00:09 +02:00
parent 877c3a68e6
commit b3b863a3c4
7 changed files with 179 additions and 123 deletions

View File

@ -96,10 +96,10 @@ void SGSky::build( double h_radius_m,
pre_transform->addChild(_ephTransform.get()); pre_transform->addChild(_ephTransform.get());
planets = new SGStars; planets = new SGStars;
_ephTransform->addChild( planets->build(eph.getNumPlanets(), eph.getPlanets(), h_radius_m) ); _ephTransform->addChild( planets->build(eph.getNumPlanets(), eph.getPlanets(), h_radius_m, options) );
stars = new SGStars(property_tree_node); stars = new SGStars(property_tree_node);
_ephTransform->addChild( stars->build(eph.getNumStars(), eph.getStars(), h_radius_m) ); _ephTransform->addChild( stars->build(eph.getNumStars(), eph.getStars(), h_radius_m, options) );
moon = new SGMoon; moon = new SGMoon;
_ephTransform->addChild( moon->build(tex_path, moon_size) ); _ephTransform->addChild( moon->build(tex_path, moon_size) );

View File

@ -31,6 +31,9 @@
#include <simgear/constants.h> #include <simgear/constants.h>
#include <simgear/debug/logstream.hxx> #include <simgear/debug/logstream.hxx>
#include <simgear/props/props.hxx> #include <simgear/props/props.hxx>
#include <simgear/scene/material/Effect.hxx>
#include <simgear/scene/material/EffectGeode.hxx>
#include <simgear/scene/util/SGReaderWriterOptions.hxx>
#include <stdio.h> #include <stdio.h>
#include <iostream> #include <iostream>
@ -48,6 +51,8 @@
#include "stars.hxx" #include "stars.hxx"
using namespace simgear;
// Constructor // Constructor
SGStars::SGStars( SGPropertyNode* props ) : SGStars::SGStars( SGPropertyNode* props ) :
old_phase(-1) old_phase(-1)
@ -67,8 +72,15 @@ SGStars::~SGStars( void ) {
// initialize the stars object and connect it into our scene graph root // initialize the stars object and connect it into our scene graph root
osg::Node* osg::Node*
SGStars::build( int num, const SGVec3d star_data[], double star_dist ) { SGStars::build( int num, const SGVec3d star_data[], double star_dist,
osg::Geode* geode = new osg::Geode; SGReaderWriterOptions* options ) {
EffectGeode* geode = new EffectGeode;
geode->setName("Stars");
Effect* effect = makeEffect("Effects/stars", true, options);
if (effect)
geode->setEffect(effect);
osg::StateSet* stateSet = geode->getOrCreateStateSet(); osg::StateSet* stateSet = geode->getOrCreateStateSet();
stateSet->setRenderBinDetails(-9, "RenderBin"); stateSet->setRenderBinDetails(-9, "RenderBin");

View File

@ -35,6 +35,10 @@
#include <simgear/structure/SGReferenced.hxx> #include <simgear/structure/SGReferenced.hxx>
#include <simgear/props/propsfwd.hxx> #include <simgear/props/propsfwd.hxx>
namespace simgear {
class SGReaderWriterOptions;
}
class SGStars : public SGReferenced { class SGStars : public SGReferenced {
osg::ref_ptr<osg::Vec4Array> cl; osg::ref_ptr<osg::Vec4Array> cl;
@ -52,7 +56,8 @@ public:
~SGStars( void ); ~SGStars( void );
// initialize the stars structure // initialize the stars structure
osg::Node* build( int num, const SGVec3d star_data[], double star_dist ); osg::Node* build( int num, const SGVec3d star_data[], double star_dist,
simgear::SGReaderWriterOptions* options );
// repaint the planet magnitudes based on current value of // repaint the planet magnitudes based on current value of
// sun_angle in degrees relative to verticle (so we can make them // sun_angle in degrees relative to verticle (so we can make them

View File

@ -34,7 +34,7 @@
#include "CompositorUtil.hxx" #include "CompositorUtil.hxx"
class LightDirectionCallback : public osg::Uniform::Callback { class SunDirectionCallback : public osg::Uniform::Callback {
public: public:
virtual void operator()(osg::Uniform *uniform, osg::NodeVisitor *nv) { virtual void operator()(osg::Uniform *uniform, osg::NodeVisitor *nv) {
SGUpdateVisitor *uv = dynamic_cast<SGUpdateVisitor *>(nv); SGUpdateVisitor *uv = dynamic_cast<SGUpdateVisitor *>(nv);
@ -140,10 +140,10 @@ Compositor::Compositor(osg::View *view,
new osg::Uniform("fg_CameraPositionGeod", osg::Vec3f()), new osg::Uniform("fg_CameraPositionGeod", osg::Vec3f()),
new osg::Uniform("fg_NearFarPlanes", osg::Vec3f()), new osg::Uniform("fg_NearFarPlanes", osg::Vec3f()),
new osg::Uniform("fg_Fcoef", 0.0f), new osg::Uniform("fg_Fcoef", 0.0f),
new osg::Uniform("fg_LightDirection", osg::Vec3f()) new osg::Uniform("fg_SunDirection", osg::Vec3f())
} }
{ {
_uniforms[LIGHT_DIRECTION]->setUpdateCallback(new LightDirectionCallback); _uniforms[SUN_DIRECTION]->setUpdateCallback(new SunDirectionCallback);
} }
Compositor::~Compositor() Compositor::~Compositor()

View File

@ -59,7 +59,7 @@ public:
CAMERA_POSITION_GEOD, CAMERA_POSITION_GEOD,
NEAR_FAR_PLANES, NEAR_FAR_PLANES,
FCOEF, FCOEF,
LIGHT_DIRECTION, SUN_DIRECTION,
TOTAL_BUILTIN_UNIFORMS TOTAL_BUILTIN_UNIFORMS
}; };

View File

@ -16,6 +16,7 @@
#include "CompositorBuffer.hxx" #include "CompositorBuffer.hxx"
#include <osg/GL>
#include <osg/Texture1D> #include <osg/Texture1D>
#include <osg/Texture2D> #include <osg/Texture2D>
#include <osg/Texture2DArray> #include <osg/Texture2DArray>
@ -23,7 +24,6 @@
#include <osg/Texture3D> #include <osg/Texture3D>
#include <osg/TextureRectangle> #include <osg/TextureRectangle>
#include <osg/TextureCubeMap> #include <osg/TextureCubeMap>
#include <osg/FrameBufferObject>
#include <simgear/props/props.hxx> #include <simgear/props/props.hxx>
#include <simgear/props/vectorPropTemplates.hxx> #include <simgear/props/vectorPropTemplates.hxx>
@ -45,13 +45,18 @@ struct BufferFormat {
PropStringMap<BufferFormat> buffer_format_map { PropStringMap<BufferFormat> buffer_format_map {
{"rgb8", {GL_RGB8, GL_RGBA, GL_UNSIGNED_BYTE}}, {"rgb8", {GL_RGB8, GL_RGBA, GL_UNSIGNED_BYTE}},
{"rgba8", {GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE}}, {"rgba8", {GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE}},
{"rgb16f", {GL_RGB16F_ARB, GL_RGBA, GL_FLOAT}}, {"rgb16f", {GL_RGB16F_ARB, GL_RGBA, GL_HALF_FLOAT}},
{"rgb32f", {GL_RGB32F_ARB, GL_RGBA, GL_FLOAT}}, {"rgb32f", {GL_RGB32F_ARB, GL_RGBA, GL_FLOAT}},
{"rgba16f", {GL_RGBA16F_ARB, GL_RGBA, GL_FLOAT}}, {"rgba16f", {GL_RGBA16F_ARB, GL_RGBA, GL_HALF_FLOAT}},
{"rgba32f", {GL_RGBA32F_ARB, GL_RGBA, GL_FLOAT}}, {"rgba32f", {GL_RGBA32F_ARB, GL_RGBA, GL_FLOAT}},
{"r8", {GL_R8, GL_RED, GL_UNSIGNED_BYTE}},
{"r16f", {GL_R16F, GL_RED, GL_HALF_FLOAT}},
{"r32f", {GL_R32F, GL_RED, GL_FLOAT}}, {"r32f", {GL_R32F, GL_RED, GL_FLOAT}},
{"rg16f", {GL_RG16F, GL_RG, GL_FLOAT}}, {"rg16f", {GL_RG16F, GL_RG, GL_HALF_FLOAT}},
{"rg32f", {GL_RG32F, GL_RG, GL_FLOAT}}, {"rg32f", {GL_RG32F, GL_RG, GL_FLOAT}},
#if defined(OSG_GL3_FEATURES)
{"r11g11b10f", {GL_R11F_G11F_B10F, GL_RGB, GL_FLOAT}},
#endif
{"depth16", {GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT}}, {"depth16", {GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT}},
{"depth24", {GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT}}, {"depth24", {GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT}},
{"depth32f", {GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT}}, {"depth32f", {GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT}},
@ -136,17 +141,32 @@ buildBuffer(Compositor *compositor, const SGPropertyNode *node,
if (p_depth) if (p_depth)
depth = p_depth->getIntValue(); depth = p_depth->getIntValue();
auto get_mipmap_levels = [&]() -> int {
int mipmap_levels = 0;
const SGPropertyNode *p_mipmap_levels = node->getNode("mipmap-levels");
if (p_mipmap_levels) {
if (p_mipmap_levels->getStringValue() == std::string("auto"))
mipmap_levels = 1 + floor(log2((float)max(max(width, height), depth)));
else
mipmap_levels = p_mipmap_levels->getIntValue();
}
return mipmap_levels;
};
if (type == "1d") { if (type == "1d") {
osg::Texture1D *tex1D = new osg::Texture1D; osg::Texture1D *tex1D = new osg::Texture1D;
tex1D->setTextureWidth(width); tex1D->setTextureWidth(width);
tex1D->setNumMipmapLevels(get_mipmap_levels());
texture = tex1D; texture = tex1D;
} else if (type == "2d") { } else if (type == "2d") {
osg::Texture2D *tex2D = new osg::Texture2D; osg::Texture2D *tex2D = new osg::Texture2D;
tex2D->setTextureSize(width, height); tex2D->setTextureSize(width, height);
tex2D->setNumMipmapLevels(get_mipmap_levels());
texture = tex2D; texture = tex2D;
} else if (type == "2d-array") { } else if (type == "2d-array") {
osg::Texture2DArray *tex2D_array = new osg::Texture2DArray; osg::Texture2DArray *tex2D_array = new osg::Texture2DArray;
tex2D_array->setTextureSize(width, height, depth); tex2D_array->setTextureSize(width, height, depth);
tex2D_array->setNumMipmapLevels(get_mipmap_levels());
texture = tex2D_array; texture = tex2D_array;
} else if (type == "2d-multisample") { } else if (type == "2d-multisample") {
osg::Texture2DMultisample *tex2DMS = new osg::Texture2DMultisample; osg::Texture2DMultisample *tex2DMS = new osg::Texture2DMultisample;
@ -156,6 +176,7 @@ buildBuffer(Compositor *compositor, const SGPropertyNode *node,
} else if (type == "3d") { } else if (type == "3d") {
osg::Texture3D *tex3D = new osg::Texture3D; osg::Texture3D *tex3D = new osg::Texture3D;
tex3D->setTextureSize(width, height, depth); tex3D->setTextureSize(width, height, depth);
tex3D->setNumMipmapLevels(get_mipmap_levels());
texture = tex3D; texture = tex3D;
} else if (type == "rect") { } else if (type == "rect") {
osg::TextureRectangle *tex_rect = new osg::TextureRectangle; osg::TextureRectangle *tex_rect = new osg::TextureRectangle;
@ -164,6 +185,7 @@ buildBuffer(Compositor *compositor, const SGPropertyNode *node,
} else if (type == "cubemap") { } else if (type == "cubemap") {
osg::TextureCubeMap *tex_cubemap = new osg::TextureCubeMap; osg::TextureCubeMap *tex_cubemap = new osg::TextureCubeMap;
tex_cubemap->setTextureSize(width, height); tex_cubemap->setTextureSize(width, height);
tex_cubemap->setNumMipmapLevels(get_mipmap_levels());
texture = tex_cubemap; texture = tex_cubemap;
} else { } else {
SG_LOG(SG_INPUT, SG_ALERT, "Unknown texture type '" << type << "'"); SG_LOG(SG_INPUT, SG_ALERT, "Unknown texture type '" << type << "'");
@ -181,7 +203,8 @@ buildBuffer(Compositor *compositor, const SGPropertyNode *node,
texture->setSourceType(format.source_type); texture->setSourceType(format.source_type);
} else { } else {
texture->setInternalFormat(GL_RGBA); texture->setInternalFormat(GL_RGBA);
SG_LOG(SG_INPUT, SG_WARN, "Unknown buffer format specified, using RGBA"); SG_LOG(SG_INPUT, SG_WARN, "Unknown buffer format '"
<< node->getStringValue("format") << "', using RGBA");
} }
osg::Texture::FilterMode filter_mode = osg::Texture::LINEAR; osg::Texture::FilterMode filter_mode = osg::Texture::LINEAR;

View File

@ -55,6 +55,76 @@ PropStringMap<osg::Camera::BufferComponent> buffer_component_map = {
{"packed-depth-stencil", osg::Camera::PACKED_DEPTH_STENCIL_BUFFER} {"packed-depth-stencil", osg::Camera::PACKED_DEPTH_STENCIL_BUFFER}
}; };
class CSMCullCallback : public osg::NodeCallback {
public:
CSMCullCallback(const std::string &suffix) {
_light_matrix_uniform = new osg::Uniform(
osg::Uniform::FLOAT_MAT4, std::string("fg_LightMatrix_") + suffix);
}
virtual void operator()(osg::Node *node, osg::NodeVisitor *nv) {
osg::Camera *camera = static_cast<osg::Camera *>(node);
traverse(node, nv);
// The light matrix uniform is updated after the traverse in case the
// OSG near/far plane calculations were enabled
osg::Matrixf light_matrix =
// Include the real camera inverse view matrix because if the shader
// used world coordinates, there would be precision issues.
_real_inverse_view *
camera->getViewMatrix() *
camera->getProjectionMatrix() *
// Bias matrices
osg::Matrix::translate(1.0, 1.0, 1.0) *
osg::Matrix::scale(0.5, 0.5, 0.5);
_light_matrix_uniform->set(light_matrix);
}
void setRealInverseViewMatrix(const osg::Matrix &matrix) {
_real_inverse_view = matrix;
}
osg::Uniform *getLightMatrixUniform() const {
return _light_matrix_uniform.get();
}
protected:
osg::Matrix _real_inverse_view;
osg::ref_ptr<osg::Uniform> _light_matrix_uniform;
};
class LightFinder : public osg::NodeVisitor {
public:
LightFinder(const std::string &name) :
osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
_name(name) {}
virtual void apply(osg::Node &node) {
// Only traverse the scene graph if we haven't found a light yet (or if
// the one we found earlier is no longer valid).
if (getLight().valid())
return;
if (node.getName() == _name) {
osg::LightSource *light_source =
dynamic_cast<osg::LightSource *>(&node);
if (light_source)
_light = light_source->getLight();
}
traverse(node);
}
osg::ref_ptr<osg::Light> getLight() const {
osg::ref_ptr<osg::Light> light_ref;
_light.lock(light_ref);
return light_ref;
}
protected:
std::string _name;
osg::observer_ptr<osg::Light> _light;
};
//------------------------------------------------------------------------------
Pass * Pass *
PassBuilder::build(Compositor *compositor, const SGPropertyNode *root, PassBuilder::build(Compositor *compositor, const SGPropertyNode *root,
@ -128,7 +198,8 @@ PassBuilder::build(Compositor *compositor, const SGPropertyNode *root,
osg::DisplaySettings::ImplicitBufferAttachmentMask implicit_attachments = 0; osg::DisplaySettings::ImplicitBufferAttachmentMask implicit_attachments = 0;
std::stringstream att_ss; std::stringstream att_ss;
std::string att_bit; std::string att_bit;
att_ss << root->getStringValue("implicit-attachment-mask", "color depth"); // No implicit attachments by default
att_ss << root->getStringValue("implicit-attachment-mask", "");
while (att_ss >> att_bit) { while (att_ss >> att_bit) {
if (att_bit == "color") implicit_attachments |= osg::DisplaySettings::IMPLICIT_COLOR_BUFFER_ATTACHMENT; if (att_bit == "color") implicit_attachments |= osg::DisplaySettings::IMPLICIT_COLOR_BUFFER_ATTACHMENT;
else if (att_bit == "depth") implicit_attachments |= osg::DisplaySettings::IMPLICIT_DEPTH_BUFFER_ATTACHMENT; else if (att_bit == "depth") implicit_attachments |= osg::DisplaySettings::IMPLICIT_DEPTH_BUFFER_ATTACHMENT;
@ -136,6 +207,30 @@ PassBuilder::build(Compositor *compositor, const SGPropertyNode *root,
} }
camera->setImplicitBufferAttachmentMask(implicit_attachments, implicit_attachments); camera->setImplicitBufferAttachmentMask(implicit_attachments, implicit_attachments);
// Set some global state
camera->getOrCreateStateSet()->setMode(GL_TEXTURE_CUBE_MAP_SEAMLESS,
osg::StateAttribute::ON);
PropertyList p_shadow_passes = root->getChildren("use-shadow-pass");
for (const auto &p_shadow_pass : p_shadow_passes) {
std::string shadow_pass_name = p_shadow_pass->getStringValue();
if (!shadow_pass_name.empty()) {
Pass *shadow_pass = compositor->getPass(shadow_pass_name);
if (shadow_pass) {
CSMCullCallback *cullcb =
dynamic_cast<CSMCullCallback *>(
shadow_pass->camera->getCullCallback());
if (cullcb) {
camera->getOrCreateStateSet()->addUniform(
cullcb->getLightMatrixUniform());
} else {
SG_LOG(SG_INPUT, SG_WARN, "ScenePassBuilder::build: Pass '"
<< shadow_pass_name << "is not a shadow pass");
}
}
}
}
PropertyList p_bindings = root->getChildren("binding"); PropertyList p_bindings = root->getChildren("binding");
for (auto const &p_binding : p_bindings) { for (auto const &p_binding : p_bindings) {
if (!checkConditional(p_binding)) if (!checkConditional(p_binding))
@ -242,6 +337,7 @@ PassBuilder::build(Compositor *compositor, const SGPropertyNode *root,
multisample_samples, multisample_samples,
multisample_color_samples); multisample_color_samples);
float mipmap_resize_factor = 1.0f / pow(2.0f, float(level));
if (!viewport_absolute && if (!viewport_absolute &&
(p_attachment->getIndex() == viewport_attachment)) { (p_attachment->getIndex() == viewport_attachment)) {
if ((buffer->width_scale == 0.0f) && if ((buffer->width_scale == 0.0f) &&
@ -250,8 +346,10 @@ PassBuilder::build(Compositor *compositor, const SGPropertyNode *root,
// relative coordinates to shape the viewport. // relative coordinates to shape the viewport.
float x = p_viewport->getFloatValue("x", 0.0f); float x = p_viewport->getFloatValue("x", 0.0f);
float y = p_viewport->getFloatValue("y", 0.0f); float y = p_viewport->getFloatValue("y", 0.0f);
float width = p_viewport->getFloatValue("width", 1.0f); float width = p_viewport->getFloatValue("width", 1.0f)
float height = p_viewport->getFloatValue("height", 1.0f); * mipmap_resize_factor;
float height = p_viewport->getFloatValue("height", 1.0f)
* mipmap_resize_factor;
camera->setViewport(x * texture->getTextureWidth(), camera->setViewport(x * texture->getTextureWidth(),
y * texture->getTextureHeight(), y * texture->getTextureHeight(),
width * texture->getTextureWidth(), width * texture->getTextureWidth(),
@ -260,13 +358,15 @@ PassBuilder::build(Compositor *compositor, const SGPropertyNode *root,
// This is a pass that should match the physical viewport // This is a pass that should match the physical viewport
// size. Store the scales so we can resize the pass later // size. Store the scales so we can resize the pass later
// if the physical viewport changes size. // if the physical viewport changes size.
pass->viewport_width_scale = buffer->width_scale; pass->viewport_width_scale = buffer->width_scale
pass->viewport_height_scale = buffer->height_scale; * mipmap_resize_factor;
pass->viewport_height_scale = buffer->height_scale
* mipmap_resize_factor;
camera->setViewport( camera->setViewport(
0, 0,
0, 0,
buffer->width_scale * compositor->getViewport()->width(), pass->viewport_width_scale * compositor->getViewport()->width(),
buffer->height_scale * compositor->getViewport()->height()); pass->viewport_height_scale * compositor->getViewport()->height());
} }
} }
} catch (sg_exception &e) { } catch (sg_exception &e) {
@ -332,6 +432,10 @@ public:
for (const auto &uniform : compositor->getUniforms()) for (const auto &uniform : compositor->getUniforms())
ss->addUniform(uniform); ss->addUniform(uniform);
int cubemap_face = root->getIntValue("cubemap-face", -1);
if (cubemap_face >= 0)
ss->addUniform(new osg::Uniform("fg_CubemapFace", cubemap_face));
return pass.release(); return pass.release();
} }
protected: protected:
@ -388,75 +492,6 @@ RegisterPassBuilder<QuadPassBuilder> registerQuadPass("quad");
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
class CSMCullCallback : public osg::NodeCallback {
public:
CSMCullCallback(const std::string &suffix) {
_light_matrix_uniform = new osg::Uniform(
osg::Uniform::FLOAT_MAT4, std::string("fg_LightMatrix_") + suffix);
}
virtual void operator()(osg::Node *node, osg::NodeVisitor *nv) {
osg::Camera *camera = static_cast<osg::Camera *>(node);
traverse(node, nv);
// The light matrix uniform is updated after the traverse in case the
// OSG near/far plane calculations were enabled
osg::Matrixf light_matrix =
// Include the real camera inverse view matrix because if the shader
// used world coordinates, there would be precision issues.
_real_inverse_view *
camera->getViewMatrix() *
camera->getProjectionMatrix() *
// Bias matrices
osg::Matrix::translate(1.0, 1.0, 1.0) *
osg::Matrix::scale(0.5, 0.5, 0.5);
_light_matrix_uniform->set(light_matrix);
}
void setRealInverseViewMatrix(const osg::Matrix &matrix) {
_real_inverse_view = matrix;
}
osg::Uniform *getLightMatrixUniform() const {
return _light_matrix_uniform.get();
}
protected:
osg::Matrix _real_inverse_view;
osg::ref_ptr<osg::Uniform> _light_matrix_uniform;
};
class LightFinder : public osg::NodeVisitor {
public:
LightFinder(const std::string &name) :
osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
_name(name) {}
virtual void apply(osg::Node &node) {
// Only traverse the scene graph if we haven't found a light yet (or if
// the one we found earlier is no longer valid).
if (getLight().valid())
return;
if (node.getName() == _name) {
osg::LightSource *light_source =
dynamic_cast<osg::LightSource *>(&node);
if (light_source)
_light = light_source->getLight();
}
traverse(node);
}
osg::ref_ptr<osg::Light> getLight() const {
osg::ref_ptr<osg::Light> light_ref;
_light.lock(light_ref);
return light_ref;
}
protected:
std::string _name;
osg::observer_ptr<osg::Light> _light;
};
struct CSMUpdateCallback : public Pass::PassUpdateCallback { struct CSMUpdateCallback : public Pass::PassUpdateCallback {
public: public:
CSMUpdateCallback(CSMCullCallback *cull_callback, CSMUpdateCallback(CSMCullCallback *cull_callback,
@ -631,26 +666,26 @@ public:
camera->setViewMatrix(view_matrix); camera->setViewMatrix(view_matrix);
camera->setProjectionMatrix(new_proj_matrix); camera->setProjectionMatrix(new_proj_matrix);
} else { } else {
osg::Vec3 camera_pos = osg::Vec3(0.0, 0.0, 0.0) * osg::Vec4d camera_pos4 = osg::Vec4d(0.0, 0.0, 0.0, 1.0) *
osg::Matrix::inverse(view_matrix); osg::Matrixd::inverse(view_matrix);
osg::Vec3d camera_pos(camera_pos4.x(), camera_pos4.y(), camera_pos4.z());
typedef std::pair<osg::Vec3, osg::Vec3> CubemapFace; typedef std::pair<osg::Vec3d, osg::Vec3d> CubemapFace;
const CubemapFace id[] = { const CubemapFace id[] = {
CubemapFace(osg::Vec3( 1, 0, 0), osg::Vec3( 0, -1, 0)), // +X CubemapFace(osg::Vec3d( 1.0, 0.0, 0.0), osg::Vec3d( 0.0, -1.0, 0.0)), // +X
CubemapFace(osg::Vec3(-1, 0, 0), osg::Vec3( 0, -1, 0)), // -X CubemapFace(osg::Vec3d(-1.0, 0.0, 0.0), osg::Vec3d( 0.0, -1.0, 0.0)), // -X
CubemapFace(osg::Vec3( 0, 1, 0), osg::Vec3( 0, 0, 1)), // +Y CubemapFace(osg::Vec3d( 0.0, 1.0, 0.0), osg::Vec3d( 0.0, 0.0, 1.0)), // +Y
CubemapFace(osg::Vec3( 0, -1, 0), osg::Vec3( 0, 0, -1)), // -Y CubemapFace(osg::Vec3d( 0.0, -1.0, 0.0), osg::Vec3d( 0.0, 0.0, -1.0)), // -Y
CubemapFace(osg::Vec3( 0, 0, 1), osg::Vec3( 0, -1, 0)), // +Z CubemapFace(osg::Vec3d( 0.0, 0.0, 1.0), osg::Vec3d( 0.0, -1.0, 0.0)), // +Z
CubemapFace(osg::Vec3( 0, 0, -1), osg::Vec3( 0, -1, 0)) // -Z CubemapFace(osg::Vec3d( 0.0, 0.0, -1.0), osg::Vec3d( 0.0, -1.0, 0.0)) // -Z
}; };
osg::Matrix cubemap_view_matrix; osg::Matrixd cubemap_view_matrix;
cubemap_view_matrix.makeLookAt(camera_pos, cubemap_view_matrix.makeLookAt(camera_pos,
camera_pos + id[_cubemap_face].first, camera_pos + id[_cubemap_face].first,
camera_pos + id[_cubemap_face].second); id[_cubemap_face].second);
camera->setViewMatrix(cubemap_view_matrix); camera->setViewMatrix(cubemap_view_matrix);
camera->setProjectionMatrixAsFrustum(-1.0, 1.0, -1.0, 1.0, camera->setProjectionMatrixAsPerspective(90.0, 1.0, znear, zfar);
znear, zfar);
} }
} }
protected: protected:
@ -706,29 +741,10 @@ public:
float zFar = root->getFloatValue("z-far", 0.0f); float zFar = root->getFloatValue("z-far", 0.0f);
pass->update_callback = new SceneUpdateCallback(cubemap_face, zNear, zFar); pass->update_callback = new SceneUpdateCallback(cubemap_face, zNear, zFar);
PropertyList p_shadow_passes = root->getChildren("use-shadow-pass");
for (const auto &p_shadow_pass : p_shadow_passes) {
std::string shadow_pass_name = p_shadow_pass->getStringValue();
if (!shadow_pass_name.empty()) {
Pass *shadow_pass = compositor->getPass(shadow_pass_name);
if (shadow_pass) {
CSMCullCallback *cullcb =
dynamic_cast<CSMCullCallback *>(
shadow_pass->camera->getCullCallback());
if (cullcb) {
camera->getOrCreateStateSet()->addUniform(
cullcb->getLightMatrixUniform());
} else {
SG_LOG(SG_INPUT, SG_WARN, "ScenePassBuilder::build: Pass '"
<< shadow_pass_name << "is not a shadow pass");
}
}
}
}
osg::StateSet *ss = camera->getOrCreateStateSet(); osg::StateSet *ss = camera->getOrCreateStateSet();
auto &uniforms = compositor->getUniforms(); auto &uniforms = compositor->getUniforms();
ss->addUniform(uniforms[Compositor::FCOEF]); ss->addUniform(uniforms[Compositor::FCOEF]);
ss->addUniform(uniforms[Compositor::SUN_DIRECTION]);
osg::ref_ptr<osg::Uniform> clustered_shading_enabled = osg::ref_ptr<osg::Uniform> clustered_shading_enabled =
new osg::Uniform("fg_ClusteredEnabled", clustered ? true : false); new osg::Uniform("fg_ClusteredEnabled", clustered ? true : false);