osg::ref_ptr<osg::CullFace> cf = new osg::CullFace;提高帧率

前言

当我使用osg绘制场景的时候,绘制大量相同图元的时候时候,如果不设置背面剔除的话,当顶点数量达到上百万个很多显卡都吃不消,帧率会掉的很快,我的显卡是NVIDIA GeForce GTX 1660 Ti

在这里插入图片描述

运行下面一段代码

//Geometry->Drawable->Node->Object->Referenced
//AlphaFunc->StateAttribute->Object->Referenced
//StateAttributeCallback->Callback->Object->Referenced
//ClearNode->Group->Node->Object->Referenced
//CoordinateSystemNode->Group->Node->Object->Referenced
//Billboard->Geode->Group->Node->Object->Referenced
//Image->BufferData->Object->Referenced
//Texture1D/Texture2D/Texture2DArray/Texture3D->Texture->TextureAttribute->StateAttribute->Object->Referenced

//Group->Node->Object->Referenced
//Geode->Group->Node->Object->Referenced
//Geometry->Drawable->Node->Object->Referenced
//AlphaFunc->StateAttribute->Object->Referenced
//StateAttributeCallback->Callback->Object->Referenced
//ClearNode->Group->Node->Object->Referenced
//CoordinateSystemNode->Group->Node->Object->Referenced
//Billboard->Geode->Group->Node->Object->Referenced
//Image->BufferData->Object->Referenced
//Texture1D/Texture2D/Texture2DArray/Texture3D->Texture->TextureAttribute->StateAttribute->Object->Referenced
//DrawArrays->PrimitiveSet->BufferData->Object->Object->Referenced
//MatrixTransform->Transform->Group->Node->Object->Referenced
//StateSet->Object

//StateAttribute->Object
//hadeModel->StateAttribute->Object
//CullFace->StateAttribute->Object
//PolygonMode->StateAttribute->Object

#include "osg/Group"
#include "osg/Geode"
#include "osg/Geometry"
#include "osg/Point"
#include "osg/Drawable"
#include "osg/StateAttribute"
#include "osg/StateSet"
#include "osg/Material"
#include "osg/MatrixTransform"
#include "osg/Matrix"
#include "osg/LightSource"
#include "osg/Light"
#include "osgDB/ReadFile"
#include "osgDB/WriteFile"
#include "osg/Notify"
#include "osg/CullFace"
#include "osgViewer/Viewer"
#include "osgUtil/Optimizer"

using namespace osg;
using namespace std;

osg::ref_ptr<osg::Geode> createLightPoint()
{
    
    
	osg::ref_ptr<osg::Geometry> geom = new osg::Geometry();

	// Don't throw away single-vertex primitives.
	//边界盒
	osg::BoundingBox bBox(-.1f, -.1f, -.1f, .1f, .1f, .1f);
	geom->setInitialBound(bBox);

	osg::ref_ptr<osg::Vec3Array> v = new osg::Vec3Array();
	geom->setVertexArray(v.get());
	v->push_back(osg::Vec3f(0.f, 0.f, 0.f));

	osg::ref_ptr<osg::Vec4Array> c = new osg::Vec4Array();
	geom->setColorArray(c.get());
	geom->setColorBinding(osg::Geometry::BIND_OVERALL);  //BIND_OVERALL:这个光源都是颜色绑定方式对应唯一的颜色:红色
	c->push_back(osg::Vec4f(1.f, 0.f, 0.f, 1.f));

	geom->addPrimitiveSet(new osg::DrawArrays(GL_POINTS, 0, 1));  //基本图元是绘制点

	//Geode是叶子节点,把Geometry加入到叶子节点中
	osg::ref_ptr<osg::Geode> geode = new osg::Geode;
	geode->addDrawable(geom.get());

	//设置状态属性
	osg::ref_ptr<StateSet> state = geode->getOrCreateStateSet();
	state->setMode(GL_LIGHTING, osg::StateAttribute::OFF | osg::StateAttribute::PROTECTED);
	osg::ref_ptr<osg::Point> pt = new osg::Point();
	pt->setSize(10.f);
	state->setAttribute(pt.get());

	return (geode.release());
	//return (geode);
}

osg::ref_ptr<osg::Drawable> createPlane()
{
    
    
	osg::ref_ptr<osg::Geometry> geom = new osg::Geometry();

	//顶点
	osg::ref_ptr<osg::Vec3Array> v = new osg::Vec3Array();
	geom->setVertexArray(v.get());
	int x, y;
	for (y = -10; y <= 10; y++)
	{
    
    
		for (x = -10; x <= 10; x++)
		{
    
    
			v->push_back(osg::Vec3((float)x * .5f, (float)y * .5f, 0.f));
		}
	}

	//法线
	osg::ref_ptr<osg::Vec3Array> n = new osg::Vec3Array();
	geom->setNormalArray(n.get());
	geom->setNormalBinding(osg::Geometry::BIND_OVERALL);
	n->push_back(osg::Vec3(0.f, 0.f, 1.f));

	//颜色
	osg::ref_ptr<osg::Vec4Array> c = new osg::Vec4Array();
	geom->setColorArray(c.get());
	geom->setColorBinding(osg::Geometry::BIND_OVERALL);
	c->push_back(osg::Vec4(1.f, 1.f, 1.f, 1.f));

	const int len(21);
	int idx(0);
	int numStrips(len - 1);
	while (numStrips--)
	{
    
    
		GLushort indices[len + len];
		int vert(0);
		while (vert < len)
		{
    
    
			indices[2 * vert + 0] = idx + len;
			indices[2 * vert + 1] = idx;
			vert++;
			idx++;
		}
		//geom->addPrimitiveSet(new osg::DrawElementsUShort(osg::PrimitiveSet::QUADS, len + len, indices));
		geom->addPrimitiveSet(new osg::DrawElementsUShort(osg::PrimitiveSet::QUAD_STRIP, len + len, indices));
	}

	return (geom.release());
}


//1.指定几何体法线
//2.允许光照并设置光照状态
//3.指定光源属性并关联到场景图形
//4.指定物体表面材质属性
//5.只有光源并没有阴影,阴影需要sogShadow来创建
osg::ref_ptr<osg::Node> createSceneGraph()
{
    
    
	// Create the root node and set state for the entire subgraph.
	osg::ref_ptr<osg::Group> group = new osg::Group();
	osg::ref_ptr<osg::Node> root = new osg::Node();
	{
    
    
		osg::ref_ptr<osg::StateSet> state = group->getOrCreateStateSet();
		state->setMode(GL_LIGHTING, osg::StateAttribute::ON);
		state->setMode(GL_LIGHT0, osg::StateAttribute::ON);
		state->setMode(GL_LIGHT1, osg::StateAttribute::ON);
	}
	// Represent the two light sources with a shared point.
	// Each light's position is 0,0,0 in object coordinates. The
	//   two parent MatrixTransforms translate the lights, and the
	//   shared point, to their actual positions.
	//osg::ref_ptr<osg::Geode> lightPoint = new osg::Geode;
	osg::ref_ptr<osg::Geode> lightPoint = createLightPoint();
	{
    
    
		
		
		osg::ref_ptr<osg::MatrixTransform> mt = new osg::MatrixTransform;
		//osg::Matrix 没有继承Referenced 所以不能用智能指针
		osg::Matrix m;
		osg::ref_ptr<RefMatrix> refM = new osg::RefMatrix;

		refM->makeTranslate(osg::Vec3(-3.f, 2.f, 5.f));
		mt->setMatrix(*refM);

		// Create a mostly red light
		osg::ref_ptr<osg::Light> light = new osg::Light;
		light->setLightNum(0);
		light->setPosition(osg::Vec4(0.f, 0.f, 0.f, 1.f));
		light->setDiffuse(osg::Vec4(1.f, .5f, .5f, 1.f));
		light->setSpecular(osg::Vec4(1.f, .8f, .8f, 1.f));

		//设置光源:第一个光源
		osg::ref_ptr<osg::LightSource> ls = new osg::LightSource;
		group->addChild(mt.get());
		//mt->setMatrix(*m);
		mt->addChild(ls.get());
		ls->setLight(light.get());
		ls->addChild(lightPoint.get());
	}

	{
    
    
		osg::ref_ptr<osg::MatrixTransform> mt = new osg::MatrixTransform;
		osg::ref_ptr<osg::RefMatrix> refM = new osg::RefMatrix;
		refM->makeTranslate(osg::Vec3(3.f, -2.f, 3.f));
		mt->setMatrix(*refM);

		// Create a mostly blue light
		osg::ref_ptr<osg::Light> light = new osg::Light;
		light->setLightNum(1);
		light->setPosition(osg::Vec4(0.f, 0.f, 0.f, 1.f));
		light->setDiffuse(osg::Vec4(.5f, .5f, 1.f, 1.f));
		light->setSpecular(osg::Vec4(.8f, .8f, 1.f, 1.f));

		//设置光源:第二个光源
		osg::ref_ptr<osg::LightSource> ls = new osg::LightSource;
		group->addChild(mt.get());
		mt->addChild(ls.get());
		ls->setLight(light.get());
		ls->addChild(lightPoint.get());
	}

	// Create a single instance of the lozenge geometry (read from disk).
	// Multiply parent it to six MatrixTransform nodes, each with their
	//   own StateSet to change the material properties of the lozenge.
	osg::ref_ptr<osg::Node> lozenge = osgDB::readNodeFile("lozenge.osg");
	if (!lozenge.valid())
	{
    
    
		osg::notify(osg::FATAL) << "Unload to load date file. Exiting." << std::endl;
		return nullptr;
	}

	{
    
    
		osg::ref_ptr<osg::MatrixTransform> mt = new osg::MatrixTransform;
		//osg::Matrix 没有继承Referenced 所以不能用智能指针
		osg::Matrix m;
		osg::ref_ptr<osg::RefMatrix> refM = new osg::RefMatrix;
		refM->makeTranslate(osg::Vec3(-1.f, -1.f, 1.f));
		mt->setMatrix(*refM);

		//设置属性
		osg::ref_ptr<osg::StateSet> state = new osg::StateSet;
		state = mt->getOrCreateStateSet();
		//背面剔除
		osg::ref_ptr<osg::CullFace> cf = new osg::CullFace;
		state->setAttributeAndModes(cf.get());
		osg::ref_ptr<osg::Material> mat = new osg::Material;
		mat->setDiffuse(osg::Material::FRONT, osg::Vec4(0.f, 0.f, 0.f, 1.f));
		mat->setSpecular(osg::Material::FRONT, osg::Vec4(1.f, 1.f, 1.f, 1.f));
		mat->setShininess(osg::Material::FRONT, 128.f);
		state->setAttribute(mat.get());

		mt->addChild(lozenge.get());
		group->addChild(mt.get());
	}
	{
    
    
		osg::ref_ptr<osg::MatrixTransform> mt = new osg::MatrixTransform;
		//osg::Matrix 没有继承Referenced 所以不能用智能指针
		osg::Matrix m;
		osg::ref_ptr<osg::RefMatrix> refM = new osg::RefMatrix;
		refM->makeTranslate(osg::Vec3(1.f, -1.f, 1.f));
		mt->setMatrix(*refM);

		//设置属性
		osg::ref_ptr<StateSet> state = mt->getOrCreateStateSet();
		//背面剔除
		osg::ref_ptr<osg::CullFace> cf = new osg::CullFace;
		state->setAttributeAndModes(cf.get());
		osg::ref_ptr<osg::Material> mat = new osg::Material;
		// Just use the object's primary color for ambient and
	   //   diffuse (uses the OpenGL color material feature).
		mat->setColorMode(osg::Material::AMBIENT_AND_DIFFUSE);
		state->setAttribute(mat.get());
		mat->setDiffuse(osg::Material::FRONT, osg::Vec4(.4f, .3f, 0.f, 1.f));
		mat->setSpecular(osg::Material::FRONT, osg::Vec4(.8f, .8f, .1f, 1.f));
		mat->setShininess(osg::Material::FRONT, 20.f);
		state->setAttribute(mat.get());

		mt->addChild(lozenge.get());
		group->addChild(mt.get());
	}

	{
    
    
		osg::ref_ptr<MatrixTransform> mt = new osg::MatrixTransform;
		//osg::Matrix 没有继承Referenced 所以不能用智能指针
		osg::Matrix m;
		osg::ref_ptr<osg::RefMatrix> refM = new osg::RefMatrix;
		refM->makeTranslate(osg::Vec3(-1.f, 0.f, 1.f));
		mt->setMatrix(*refM);

		osg::ref_ptr<osg::StateSet> state = mt->getOrCreateStateSet();
		//背面剔除
		osg::ref_ptr<osg::CullFace> cf = new osg::CullFace;
		state->setAttributeAndModes(cf.get());
		osg::ref_ptr<osg::Material> mat = new osg::Material;
		mat->setDiffuse(osg::Material::FRONT, osg::Vec4(.4f, .3f, 0.f, 1.f));
		mat->setSpecular(osg::Material::FRONT, osg::Vec4(.8f, .8f, 1.f, 1.f));
		mat->setShininess(osg::Material::FRONT, 20.f);
		state->setAttribute(mat.get());

		mt->addChild(lozenge.get());
		group->addChild(mt.get());
	}

	{
    
    
		osg::ref_ptr<osg::MatrixTransform> mt = new osg::MatrixTransform;
		//osg::Matrix 没有继承Referenced 所以不能用智能指针
		osg::Matrix m;
		osg::ref_ptr<osg::RefMatrix> refM = new osg::RefMatrix;
		refM->makeTranslate(osg::Vec3(1.f, 0.f, 1.f));
		mt->setMatrix(*refM);

		//设置属性
		osg::ref_ptr<osg::StateSet> state = mt->getOrCreateStateSet();
		//背面剔除
		osg::ref_ptr<osg::CullFace> cf = new osg::CullFace;
		state->setAttributeAndModes(cf.get());
		osg::ref_ptr<osg::Material> mat = new osg::Material;
		mat->setDiffuse(osg::Material::FRONT, osg::Vec4(.1f, .2f, .5f, 1.f));
		mat->setSpecular(osg::Material::FRONT, osg::Vec4(.9f, .9f, 1.f, 1.f));
		mat->setShininess(osg::Material::FRONT, 10.f);
		state->setAttribute(mat.get());

		mt->addChild(lozenge.get());
		group->addChild(mt.get());
	}

	{
    
    
		osg::ref_ptr<osg::MatrixTransform> mt = new osg::MatrixTransform;
		//osg::Matrix 没有继承Referenced 所以不能用智能指针
		osg::Matrix m;
		osg::ref_ptr<osg::RefMatrix> refM = new osg::RefMatrix;
		refM->makeTranslate(osg::Vec3(-1.f, 1.f, 1.f));
		mt->setMatrix(*refM);

		osg::ref_ptr<osg::StateSet> state = mt->getOrCreateStateSet();
		//背面剔除
		osg::ref_ptr<osg::CullFace> cf = new osg::CullFace;
		state->setAttributeAndModes(cf.get());
		osg::ref_ptr<osg::Material> mat = new osg::Material;
		mat->setDiffuse(osg::Material::FRONT, osg::Vec4(.2f, .9f, .9f, 1.f));
		mat->setSpecular(osg::Material::FRONT, osg::Vec4(1.f, 1.f, 1.f, 1.f));
		mat->setShininess(osg::Material::FRONT, 96.f);
		state->setAttribute(mat.get());

		mt->addChild(lozenge.get());
		group->addChild(mt.get());
	}

	{
    
    
		osg::ref_ptr<osg::MatrixTransform> mt = new osg::MatrixTransform;
		osg::ref_ptr<osg::RefMatrix> refM = new osg::RefMatrix;
		refM->makeTranslate(osg::Vec3(1.f, 1.f, 1.f));
		mt->setMatrix(*refM);

		osg::ref_ptr<osg::StateSet> state = mt->getOrCreateStateSet();
		//背面剔除
		osg::ref_ptr<osg::CullFace> cf = new osg::CullFace;
		state->setAttributeAndModes(cf.get());
		osg::ref_ptr<osg::Material> mat = new osg::Material;
		mat->setDiffuse(osg::Material::FRONT, osg::Vec4(1.f, 1.f, 1.f, 1.f));
		mat->setSpecular(osg::Material::FRONT, osg::Vec4(0.f, 0.f, 0.f, 1.f));
		mat->setShininess(Material::FRONT, 0.f);
		state->setAttribute(mat.get());

		mt->addChild(lozenge.get());
		group->addChild(mt.get());

	}


	osg::ref_ptr<osg::Geode> planeGeode = new osg::Geode;
	planeGeode->addDrawable(createPlane());
	{
    
    
		osg::ref_ptr<osg::StateSet> state = new osg::StateSet;
		state = planeGeode->getOrCreateStateSet();
		//背面剔除
		osg::ref_ptr<osg::CullFace> cf = new osg::CullFace;
		state->setAttributeAndModes(cf.get());
		osg::ref_ptr<osg::Material> mat = new osg::Material;
		mat->setDiffuse(osg::Material::FRONT, osg::Vec4(.6f, .5f, .2f, 1.f));
		mat->setSpecular(osg::Material::FRONT, osg::Vec4(.4f, .4f, .4f, 1.f));
		mat->setShininess(osg::Material::FRONT, 128.f);
		state->setAttribute(mat.get());

		/*osg::ref_ptr<osg::CullFace> cf = new osg::CullFace;
		state->setAttributeAndModes(cf.get());*/
	}

	group->addChild(planeGeode.get());

	return group.release();
}

int main(int argc, char** argv)
{
    
    
	osg::ref_ptr<osg::Node> root = createSceneGraph();
	if (!root.valid())
	{
    
    
		osg::notify(osg::FATAL) << "Failed in createSceneGraph()." << std::endl;
		return (1);
	}

	

	//每次执行writeNodeFile都会往lozenge.osg文件中写入顶点,默认是追加写入,所以lozenge.osg文件会越来越大,直到显卡崩溃
	std::string out("lozenge.osg");
	if (!(osgDB::writeNodeFile(*(root.get()), out)))
	{
    
    
		osg::notify(osg::FATAL) << "Failed in osgDB::writeNodeFile()." << std::endl;
		return (1);
	}

	osg::notify(osg::ALWAYS) << "Successfully wrote \"" << out << "\". Execute \"osgviewer " << out << "\" to view." << endl;

	osgViewer::Viewer viewer;
	auto node = osgDB::readNodeFile("lozenge.osg");
	osgUtil::Optimizer opt;
	opt.optimize(node);
	//node->setUseDisplayList(false);
	auto geom = node->asGeometry();
	//geom->setUseVertexArrayObject(true);



	viewer.setSceneData(node);

	return viewer.run();
}

使用window PowerShell 运行osgviewer.exe lozenge.osg
在这里插入图片描述
当达到400多万个顶点,帧率只有不到30帧,这还是使用了osg::CullFace,如果不用背面剔除,帧率变下降到原来的五分之一左右,大概6帧的样子
在这里插入图片描述

在这里插入图片描述

工程源码

工程源码下载地址

猜你喜欢

转载自blog.csdn.net/aoxuestudy/article/details/121144766
今日推荐