Add support for glTF transparent objects

Also added some Compositor uniforms.
This commit is contained in:
Fernando García Liñán 2021-08-19 01:40:24 +02:00
parent 2b9933c0b5
commit 6cea6b7fdf
4 changed files with 57 additions and 24 deletions

View File

@ -135,12 +135,12 @@ struct GLTFBuilder {
group->addChild(geode); group->addChild(geode);
SGPropertyNode_ptr effectRoot = new SGPropertyNode; SGPropertyNode_ptr effectRoot = new SGPropertyNode;
// Material is OPAQUE by default, so inherit from model-pbr
makeChild(effectRoot, "inherits-from")->setStringValue("Effects/model-pbr"); makeChild(effectRoot, "inherits-from")->setStringValue("Effects/model-pbr");
if (primitive.material >= 0) { if (primitive.material >= 0) {
// We have a material assigned to the primitive, add all the // We have a material assigned to the primitive, add all the
// required material info as parameters to the Effect. // required material info as parameters to the Effect.
makeMaterialParameters(makeChild(effectRoot, "parameters"), makeMaterialParameters(effectRoot, model.materials[primitive.material]);
model.materials[primitive.material]);
} }
Effect *effect = makeEffect(effectRoot, true, opts); Effect *effect = makeEffect(effectRoot, true, opts);
if (effect) if (effect)
@ -212,10 +212,24 @@ struct GLTFBuilder {
return group; return group;
} }
bool makeMaterialParameters(SGPropertyNode *params, bool makeMaterialParameters(SGPropertyNode *effectRoot,
const tinygltf::Material &material) const { const tinygltf::Material &material) const {
SGPropertyNode *params = makeChild(effectRoot, "parameters");
const tinygltf::PbrMetallicRoughness &pbr = material.pbrMetallicRoughness; 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( makeChild(params, "base-color-factor")->setValue(
SGVec4d(pbr.baseColorFactor[0], SGVec4d(pbr.baseColorFactor[0],
pbr.baseColorFactor[1], pbr.baseColorFactor[1],
@ -228,21 +242,6 @@ struct GLTFBuilder {
material.emissiveFactor[1], material.emissiveFactor[1],
material.emissiveFactor[2])); 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; std::string cullFaceString;
if (material.doubleSided) { if (material.doubleSided) {
cullFaceString = "off"; cullFaceString = "off";

View File

@ -135,7 +135,7 @@ Compositor::Compositor(osg::View *view,
_gc(gc), _gc(gc),
_viewport(viewport), _viewport(viewport),
_uniforms{ _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_ViewMatrix", osg::Matrixf()),
new osg::Uniform("fg_ViewMatrixInverse", osg::Matrixf()), new osg::Uniform("fg_ViewMatrixInverse", osg::Matrixf()),
new osg::Uniform("fg_ProjectionMatrix", 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_PrevProjectionMatrixInverse", osg::Matrixf()),
new osg::Uniform("fg_CameraPositionCart", osg::Vec3f()), new osg::Uniform("fg_CameraPositionCart", osg::Vec3f()),
new osg::Uniform("fg_CameraPositionGeod", 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_NearFar", osg::Vec2f()),
new osg::Uniform("fg_Planes", osg::Vec3f()), new osg::Uniform("fg_Planes", osg::Vec3f()),
new osg::Uniform("fg_SunDirection", osg::Vec3f()), new osg::Uniform("fg_SunDirection", osg::Vec3f()),
new osg::Uniform("fg_SunDirectionWorld", 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( _uniforms[SG_UNIFORM_SUN_DIRECTION_WORLD]->setUpdateCallback(
@ -176,10 +180,16 @@ Compositor::update(const osg::Matrix &view_matrix,
// Update uniforms // Update uniforms
osg::Matrixd view_inverse = osg::Matrix::inverse(view_matrix); 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( SGGeod camera_pos_geod = SGGeod::fromCart(
SGVec3d(camera_pos.x(), camera_pos.y(), camera_pos.z())); 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, double left = 0.0, right = 0.0, bottom = 0.0, top = 0.0,
zNear = 0.0, zFar = 0.0; zNear = 0.0, zFar = 0.0;
proj_matrix.getFrustum(left, right, bottom, top, zNear, zFar); 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) { for (int i = 0; i < SG_TOTAL_BUILTIN_UNIFORMS; ++i) {
osg::ref_ptr<osg::Uniform> u = _uniforms[i]; osg::ref_ptr<osg::Uniform> u = _uniforms[i];
switch (i) { switch (i) {
case SG_UNIFORM_VIEWPORT_SIZE: case SG_UNIFORM_VIEWPORT:
u->set(osg::Vec2f(_viewport->width(), _viewport->height())); u->set(osg::Vec4f(_viewport->x(), _viewport->y(),
_viewport->width(), _viewport->height()));
break; break;
case SG_UNIFORM_VIEW_MATRIX: case SG_UNIFORM_VIEW_MATRIX:
u->set(view_matrix); u->set(view_matrix);
@ -220,13 +231,16 @@ Compositor::update(const osg::Matrix &view_matrix,
u->set(osg::Matrix::inverse(proj_matrix)); u->set(osg::Matrix::inverse(proj_matrix));
break; break;
case SG_UNIFORM_CAMERA_POSITION_CART: 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; break;
case SG_UNIFORM_CAMERA_POSITION_GEOD: case SG_UNIFORM_CAMERA_POSITION_GEOD:
u->set(osg::Vec3f(camera_pos_geod.getLongitudeRad(), u->set(osg::Vec3f(camera_pos_geod.getLongitudeRad(),
camera_pos_geod.getLatitudeRad(), camera_pos_geod.getLatitudeRad(),
camera_pos_geod.getElevationM())); camera_pos_geod.getElevationM()));
break; break;
case SG_UNIFORM_CAMERA_DISTANCE_TO_EARTH_CENTER:
u->set(float(camera_pos.length()));
break;
case SG_UNIFORM_NEAR_FAR: case SG_UNIFORM_NEAR_FAR:
u->set(osg::Vec2f(zNear, zFar)); u->set(osg::Vec2f(zNear, zFar));
break; break;
@ -236,6 +250,15 @@ Compositor::update(const osg::Matrix &view_matrix,
case SG_UNIFORM_SUN_DIRECTION: case SG_UNIFORM_SUN_DIRECTION:
u->set(osg::Vec3f(sun_dir_view.x(), sun_dir_view.y(), sun_dir_view.z())); u->set(osg::Vec3f(sun_dir_view.x(), sun_dir_view.y(), sun_dir_view.z()));
break; 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: default:
// Unknown uniform // Unknown uniform
break; break;

View File

@ -46,7 +46,7 @@ namespace compositor {
class Compositor { class Compositor {
public: public:
enum BuiltinUniform { enum BuiltinUniform {
SG_UNIFORM_VIEWPORT_SIZE = 0, SG_UNIFORM_VIEWPORT = 0,
SG_UNIFORM_VIEW_MATRIX, SG_UNIFORM_VIEW_MATRIX,
SG_UNIFORM_VIEW_MATRIX_INV, SG_UNIFORM_VIEW_MATRIX_INV,
SG_UNIFORM_PROJECTION_MATRIX, SG_UNIFORM_PROJECTION_MATRIX,
@ -57,10 +57,14 @@ public:
SG_UNIFORM_PREV_PROJECTION_MATRIX_INV, SG_UNIFORM_PREV_PROJECTION_MATRIX_INV,
SG_UNIFORM_CAMERA_POSITION_CART, SG_UNIFORM_CAMERA_POSITION_CART,
SG_UNIFORM_CAMERA_POSITION_GEOD, SG_UNIFORM_CAMERA_POSITION_GEOD,
SG_UNIFORM_CAMERA_DISTANCE_TO_EARTH_CENTER,
SG_UNIFORM_NEAR_FAR, SG_UNIFORM_NEAR_FAR,
SG_UNIFORM_PLANES, SG_UNIFORM_PLANES,
SG_UNIFORM_SUN_DIRECTION, SG_UNIFORM_SUN_DIRECTION,
SG_UNIFORM_SUN_DIRECTION_WORLD, SG_UNIFORM_SUN_DIRECTION_WORLD,
SG_UNIFORM_SUN_ZENITH_COSTHETA,
SG_UNIFORM_EARTH_RADIUS,
SG_UNIFORM_WORLD_UP,
SG_TOTAL_BUILTIN_UNIFORMS SG_TOTAL_BUILTIN_UNIFORMS
}; };

View File

@ -765,8 +765,15 @@ public:
osg::StateSet *ss = camera->getOrCreateStateSet(); osg::StateSet *ss = camera->getOrCreateStateSet();
auto &uniforms = compositor->getBuiltinUniforms(); 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]);
ss->addUniform(uniforms[Compositor::SG_UNIFORM_SUN_DIRECTION_WORLD]); 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<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);