osgModelLightZ-Lighting - osg模型调整光照以及模型闪烁问题[z-lighting]

osg模型调整光照以及模型闪烁问题[z-lighting]

0 模型闪烁原因推测

  • 1 关于模型闪烁的问题,很可能是由于坐标的值的有效位数超过了7位,目前的opengl的gpu渲染(老一点的显卡以及gl)都是以单精度来渲染点的位置的,所以如果坐标很大,很可能导致单精度无法精确表示有效位数超过7位的数据,然后发生截断。
  • 2 关于z-lighting的问题,尝试了网上大多数的方法:可以使用osg封装的polygonOffset来避免重叠面片交替出现的问题,当然最好的方案是找的模型本身重叠面片就少

1 meshlab手动调模型

filters->Normals,curve,orientations->transform…

2 使用osg降低模型的点的坐标大小

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
osg::Vec3f center1 = TerrainM1->getBound().center();
float radius1 = TerrainM1->getBound().radius();
osg::Vec3f center2 = TerrainM2->getBound().center();
float radius2 = TerrainM2->getBound().radius();
TerrainM1->setMatrix(
osg::Matrix::translate(-center1.x(), -center1.y(), -center1.z()) *
osg::Matrix::rotate(osg::DegreesToRadians(180.0), 1, 0, 0) *
osg::Matrix::translate(center1.x(), center1.y(), center1.z()) *
osg::Matrix::translate(0, 0, radius2 * 0.80 + radius1)
);

// to modify the model's points render value
mRoot->getChild(0)->asTransform()->asMatrixTransform()->setMatrix(
osg::Matrix::translate(-center1.x(), -center1.y(), -center1.z())
);
osgDB::writeNodeFile(*(mRoot->getChild(0)->asNode()), "sc.obj");

3 关于材质,光照,以及模型读写旋转平移的例子

关于材料的颜色光照等可以参考https://learnopengl-cn.readthedocs.io/zh/latest/02%20Lighting/03%20Materials/

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
 // mRoot是一个osg::ref_ptr<osg::Group>
auto TerrainM1 = new osg::MatrixTransform;
auto terrain1 = new osg::PositionAttitudeTransform;

auto TerrainM2 = new osg::MatrixTransform;
auto terrain2 = new osg::PositionAttitudeTransform;
osgDB::Options *a = new osgDB::Options(std::string("noRotation")); // 关掉模型优化绘制(OSG在加载obj模型的时候,会默认将模型绕x轴逆时针旋转90度,此处设置不旋转)

// setting material
osg::Material *material = new osg::Material;
material->setDiffuse(osg::Material::FRONT, osg::Vec4(0.75, 0.80, 0.75, 1.0));
material->setAmbient(osg::Material::FRONT, osg::Vec4(0.75, 0.80, 0.75, 1.0));
// material->setShininess(osg::Material::FRONT, 90.0);

// turn off light effect
auto Model1 = osgDB::readNodeFile(part1Path, a);
auto pState1 = Model1->getOrCreateStateSet();
pState1->setMode(GL_LIGHTING, osg::StateAttribute::ON);
pState1->setAttribute(material);
// pState1->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF | osg::StateAttribute::OVERRIDE);
// pState1->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
// set polygon offset
osg::ref_ptr<osg::PolygonOffset> polyOff = new osg::PolygonOffset();
float mFactor = 1.0, mUnits = 1.0;
polyOff->setFactor(mFactor);
polyOff->setUnits(mUnits);
pState1->setAttributeAndModes(new osg::PolygonOffset(-1.0f,-1.0f),osg::StateAttribute::ON);
material->setEmission(osg::Material::FRONT, osg::Vec4(0.75, 0.80, 0.75, 1.0));
// pState1->setAttributeAndModes(polyOff.get(), osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);

// auto pGeom1 = Model1->asGeode()->asGeometry();
// pGeom1->getOrCreateStateSet()->setMode(GL_NV_framebuffer_multisample_coverage, osg::StateAttribute::ON | osg::StateAttribute::PROTECTED | osg::StateAttribute::OVERRIDE);
TerrainM1->addChild(Model1);
TerrainM1->setName(modelPrefix + "1");


auto Model2 = osgDB::readNodeFile(part2Path, a);
auto pState2 = Model2->getOrCreateStateSet();
pState2->setMode(GL_LIGHTING, osg::StateAttribute::ON);
pState2->setAttribute(material);

pState2->setMode(GL_BLEND, osg::StateAttribute::ON);
TerrainM2->addChild(Model2);
TerrainM2->setName(modelPrefix + "2");



// rotate to make sure the building is standing on the ground
osg::Vec3f center1 = TerrainM1->getBound().center();
float radius1 = TerrainM1->getBound().radius();
osg::Vec3f center2 = TerrainM2->getBound().center();
float radius2 = TerrainM2->getBound().radius();
TerrainM1->setMatrix(
osg::Matrix::translate(-center1.x(), -center1.y(), -center1.z()) *
osg::Matrix::rotate(osg::DegreesToRadians(180.0), 1, 0, 0) *
osg::Matrix::translate(center1.x(), center1.y(), center1.z()) *
osg::Matrix::translate(0, 0, radius2 * 0.80 + radius1)
);
mRoot->addChild(TerrainM1);
TerrainM2->setMatrix(
osg::Matrix::translate(-center2.x(), -center2.y(), -center2.z()) *
osg::Matrix::rotate(osg::DegreesToRadians(180.0), 1, 0, 0) *
osg::Matrix::translate(center2.x(), center2.y(), center2.z()) *
osg::Matrix::translate(0, 0, 0.5 * radius2)
);
mRoot->addChild(TerrainM2);

// to modify the model's points render value
mRoot->getChild(0)->asTransform()->asMatrixTransform()->setMatrix(
osg::Matrix::translate(-center1.x(), -center1.y(), -center1.z())
);
mRoot->getChild(1)->asTransform()->asMatrixTransform()->setMatrix(
osg::Matrix::translate(-center1.x(), -center1.y(), -center1.z())
);
mRoot->getChild(4)->asTransform()->asMatrixTransform()->setMatrix(
osg::Matrix::translate(-center1.x(), -center1.y(), -center1.z())
);
mRoot->getChild(5)->asTransform()->asMatrixTransform()->setMatrix(
osg::Matrix::translate(-center1.x(), -center1.y(), -center1.z())
);


osgDB::writeNodeFile(*(mRoot->getChild(0)->asNode()), "sc.obj");
osgDB::writeNodeFile(*(mRoot->getChild(1)->asNode()), "de.obj");
osgDB::writeNodeFile(*(mRoot->getChild(4)->asNode()), "par1.obj");
osgDB::writeNodeFile(*(mRoot->getChild(5)->asNode()), "par2.obj");