diff --git a/simgear/scene/model/ReaderWriterGLTF.cxx b/simgear/scene/model/ReaderWriterGLTF.cxx index 99a7b174..aa199735 100644 --- a/simgear/scene/model/ReaderWriterGLTF.cxx +++ b/simgear/scene/model/ReaderWriterGLTF.cxx @@ -135,12 +135,12 @@ struct GLTFBuilder { group->addChild(geode); SGPropertyNode_ptr effectRoot = new SGPropertyNode; + // Material is OPAQUE by default, so inherit from model-pbr makeChild(effectRoot, "inherits-from")->setStringValue("Effects/model-pbr"); if (primitive.material >= 0) { // We have a material assigned to the primitive, add all the // required material info as parameters to the Effect. - makeMaterialParameters(makeChild(effectRoot, "parameters"), - model.materials[primitive.material]); + makeMaterialParameters(effectRoot, model.materials[primitive.material]); } Effect *effect = makeEffect(effectRoot, true, opts); if (effect) @@ -212,10 +212,24 @@ struct GLTFBuilder { return group; } - bool makeMaterialParameters(SGPropertyNode *params, + bool makeMaterialParameters(SGPropertyNode *effectRoot, const tinygltf::Material &material) const { + SGPropertyNode *params = makeChild(effectRoot, "parameters"); const tinygltf::PbrMetallicRoughness &pbr = material.pbrMetallicRoughness; + // Handle transparent modes + // We have a separate Effect for transparent objects, so inherit from + // that instead. + if (material.alphaMode == "MASK") { + effectRoot->setStringValue("inherits-from", "Effects/model-pbr-transparent"); + makeChild(params, "blend")->setValue(0); + makeChild(params, "alpha-cutoff")->setValue(material.alphaCutoff); + } else if (material.alphaMode == "BLEND") { + effectRoot->setStringValue("inherits-from", "Effects/model-pbr-transparent"); + makeChild(params, "blend")->setValue(1); + makeChild(params, "alpha-cutoff")->setValue(-1.0); + } + makeChild(params, "base-color-factor")->setValue( SGVec4d(pbr.baseColorFactor[0], pbr.baseColorFactor[1], @@ -228,21 +242,6 @@ struct GLTFBuilder { material.emissiveFactor[1], material.emissiveFactor[2])); - SGPropertyNode *blendNode = makeChild(params, "blend"); - if (material.alphaMode == "OPAQUE") { - makeChild(blendNode, "active")->setValue(false); - makeChild(params, "rendering-hint")->setStringValue("opaque"); - makeChild(params, "alpha-cutoff")->setValue(-1.0); - } else if (material.alphaMode == "MASK") { - makeChild(blendNode, "active")->setValue(false); - makeChild(params, "rendering-hint")->setStringValue("opaque"); - makeChild(params, "alpha-cutoff")->setValue(material.alphaCutoff); - } else if (material.alphaMode == "BLEND") { - makeChild(blendNode, "active")->setValue(true); - makeChild(params, "rendering-hint")->setStringValue("transparent"); - makeChild(params, "alpha-cutoff")->setValue(-1.0); - } - std::string cullFaceString; if (material.doubleSided) { cullFaceString = "off"; diff --git a/simgear/scene/viewer/Compositor.cxx b/simgear/scene/viewer/Compositor.cxx index 15188e9d..617192bf 100644 --- a/simgear/scene/viewer/Compositor.cxx +++ b/simgear/scene/viewer/Compositor.cxx @@ -135,7 +135,7 @@ Compositor::Compositor(osg::View *view, _gc(gc), _viewport(viewport), _uniforms{ - new osg::Uniform("fg_ViewportSize", osg::Vec2f()), + new osg::Uniform("fg_Viewport", osg::Vec4f()), new osg::Uniform("fg_ViewMatrix", osg::Matrixf()), new osg::Uniform("fg_ViewMatrixInverse", osg::Matrixf()), new osg::Uniform("fg_ProjectionMatrix", osg::Matrixf()), @@ -146,10 +146,14 @@ Compositor::Compositor(osg::View *view, new osg::Uniform("fg_PrevProjectionMatrixInverse", osg::Matrixf()), new osg::Uniform("fg_CameraPositionCart", osg::Vec3f()), new osg::Uniform("fg_CameraPositionGeod", osg::Vec3f()), + new osg::Uniform("fg_CameraDistanceToEarthCenter", 0.0f), new osg::Uniform("fg_NearFar", osg::Vec2f()), new osg::Uniform("fg_Planes", osg::Vec3f()), new osg::Uniform("fg_SunDirection", osg::Vec3f()), new osg::Uniform("fg_SunDirectionWorld", osg::Vec3f()), + new osg::Uniform("fg_SunZenithCosTheta", 0.0f), + new osg::Uniform("fg_EarthRadius", 0.0f), + new osg::Uniform("fg_WorldUp", osg::Vec3f()), } { _uniforms[SG_UNIFORM_SUN_DIRECTION_WORLD]->setUpdateCallback( @@ -176,10 +180,16 @@ Compositor::update(const osg::Matrix &view_matrix, // Update uniforms osg::Matrixd view_inverse = osg::Matrix::inverse(view_matrix); - osg::Vec4d camera_pos = osg::Vec4(0.0, 0.0, 0.0, 1.0) * view_inverse; + osg::Vec4d camera_pos4 = osg::Vec4d(0.0, 0.0, 0.0, 1.0) * view_inverse; + osg::Vec3d camera_pos = osg::Vec3d(camera_pos4.x(), + camera_pos4.y(), + camera_pos4.z()); SGGeod camera_pos_geod = SGGeod::fromCart( SGVec3d(camera_pos.x(), camera_pos.y(), camera_pos.z())); + osg::Vec3d world_up = camera_pos; + world_up.normalize(); + double left = 0.0, right = 0.0, bottom = 0.0, top = 0.0, zNear = 0.0, zFar = 0.0; proj_matrix.getFrustum(left, right, bottom, top, zNear, zFar); @@ -204,8 +214,9 @@ Compositor::update(const osg::Matrix &view_matrix, for (int i = 0; i < SG_TOTAL_BUILTIN_UNIFORMS; ++i) { osg::ref_ptr u = _uniforms[i]; switch (i) { - case SG_UNIFORM_VIEWPORT_SIZE: - u->set(osg::Vec2f(_viewport->width(), _viewport->height())); + case SG_UNIFORM_VIEWPORT: + u->set(osg::Vec4f(_viewport->x(), _viewport->y(), + _viewport->width(), _viewport->height())); break; case SG_UNIFORM_VIEW_MATRIX: u->set(view_matrix); @@ -220,13 +231,16 @@ Compositor::update(const osg::Matrix &view_matrix, u->set(osg::Matrix::inverse(proj_matrix)); break; case SG_UNIFORM_CAMERA_POSITION_CART: - u->set(osg::Vec3f(camera_pos.x(), camera_pos.y(), camera_pos.z())); + u->set(osg::Vec3f(camera_pos)); break; case SG_UNIFORM_CAMERA_POSITION_GEOD: u->set(osg::Vec3f(camera_pos_geod.getLongitudeRad(), camera_pos_geod.getLatitudeRad(), camera_pos_geod.getElevationM())); break; + case SG_UNIFORM_CAMERA_DISTANCE_TO_EARTH_CENTER: + u->set(float(camera_pos.length())); + break; case SG_UNIFORM_NEAR_FAR: u->set(osg::Vec2f(zNear, zFar)); break; @@ -236,6 +250,15 @@ Compositor::update(const osg::Matrix &view_matrix, case SG_UNIFORM_SUN_DIRECTION: u->set(osg::Vec3f(sun_dir_view.x(), sun_dir_view.y(), sun_dir_view.z())); break; + case SG_UNIFORM_SUN_ZENITH_COSTHETA: + u->set(float(sun_dir_world * world_up)); + break; + case SG_UNIFORM_EARTH_RADIUS: + u->set(float(camera_pos.length() - camera_pos_geod.getElevationM())); + break; + case SG_UNIFORM_WORLD_UP: + u->set(osg::Vec3f(world_up)); + break; default: // Unknown uniform break; diff --git a/simgear/scene/viewer/Compositor.hxx b/simgear/scene/viewer/Compositor.hxx index fa621a91..f5c3e703 100644 --- a/simgear/scene/viewer/Compositor.hxx +++ b/simgear/scene/viewer/Compositor.hxx @@ -46,7 +46,7 @@ namespace compositor { class Compositor { public: enum BuiltinUniform { - SG_UNIFORM_VIEWPORT_SIZE = 0, + SG_UNIFORM_VIEWPORT = 0, SG_UNIFORM_VIEW_MATRIX, SG_UNIFORM_VIEW_MATRIX_INV, SG_UNIFORM_PROJECTION_MATRIX, @@ -57,10 +57,14 @@ public: SG_UNIFORM_PREV_PROJECTION_MATRIX_INV, SG_UNIFORM_CAMERA_POSITION_CART, SG_UNIFORM_CAMERA_POSITION_GEOD, + SG_UNIFORM_CAMERA_DISTANCE_TO_EARTH_CENTER, SG_UNIFORM_NEAR_FAR, SG_UNIFORM_PLANES, SG_UNIFORM_SUN_DIRECTION, SG_UNIFORM_SUN_DIRECTION_WORLD, + SG_UNIFORM_SUN_ZENITH_COSTHETA, + SG_UNIFORM_EARTH_RADIUS, + SG_UNIFORM_WORLD_UP, SG_TOTAL_BUILTIN_UNIFORMS }; diff --git a/simgear/scene/viewer/CompositorPass.cxx b/simgear/scene/viewer/CompositorPass.cxx index c5588d65..ff75f3ef 100644 --- a/simgear/scene/viewer/CompositorPass.cxx +++ b/simgear/scene/viewer/CompositorPass.cxx @@ -765,8 +765,15 @@ public: osg::StateSet *ss = camera->getOrCreateStateSet(); auto &uniforms = compositor->getBuiltinUniforms(); + ss->addUniform(uniforms[Compositor::SG_UNIFORM_VIEWPORT]); + ss->addUniform(uniforms[Compositor::SG_UNIFORM_CAMERA_POSITION_CART]); + ss->addUniform(uniforms[Compositor::SG_UNIFORM_CAMERA_POSITION_GEOD]); + ss->addUniform(uniforms[Compositor::SG_UNIFORM_CAMERA_DISTANCE_TO_EARTH_CENTER]); ss->addUniform(uniforms[Compositor::SG_UNIFORM_SUN_DIRECTION]); ss->addUniform(uniforms[Compositor::SG_UNIFORM_SUN_DIRECTION_WORLD]); + ss->addUniform(uniforms[Compositor::SG_UNIFORM_SUN_ZENITH_COSTHETA]); + ss->addUniform(uniforms[Compositor::SG_UNIFORM_EARTH_RADIUS]); + ss->addUniform(uniforms[Compositor::SG_UNIFORM_WORLD_UP]); osg::ref_ptr clustered_shading_enabled = new osg::Uniform("fg_ClusteredEnabled", clustered ? true : false);