ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

OSG数据加载性能优化:合并几何体

2021-07-05 14:02:47  阅读:351  来源: 互联网

标签:Vec3 Geometry 几何体 geom OSG new 0.45 osg 加载


1、理论知识

OSG最终绘制的都是osg::Geometry,然后Geometry会存放在Node里。比如我们要绘制10条线,那么我们有两种方法,一种方法是定义10个Geometry,每个Geometry定义两个顶点绘制1条线。另一个方法是我们定义1个Geometry,里面放20个顶点,一次性绘制10条线。这两种方法的性能差异很大。

方法一因为定义了10个Geometry,那么CPU端就会做Event、Cull、Update、Draw都会针对10个结点来做,很花性能。GPU也会接受10次来自CPU端的数据,之间通信也会增加,GPU端的绘制工作量也会增加变缓。如下是cookbook8,绘制了300x300=90000个Geometry。每个Geometry只有4个顶点时的数据绘制效率:
在这里插入图片描述
而方法二是只定义1个Geometry,压入了300x300x4=36万个顶点,也是90000个四边形,一个四边形是4个顶点。绘制的结果是一模一样的,但是其性能就会大幅提升:
在这里插入图片描述
总之来说,将多个Geometry合并成一个Geometry几乎是业界普遍认为最简单、最有效、最普遍、最应该使用的优化方法。也就是CPU尽量少次多量的向GPU提交数据

2、附上代码如下

// osgPro221.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <windows.h>
#include <iostream>

/* -*-c++-*- OpenSceneGraph Cookbook
 * Chapter 8 Recipe 1
 * Author: Wang Rui <wangray84 at gmail dot com>
*/

#include <osg/Geometry>
#include <osg/Group>
#include <osgDB/ReadFile>
#include <osgViewer/ViewerEventHandlers>
#include <osgViewer/Viewer>

#pragma comment(lib, "OpenThreadsd.lib")
#pragma comment(lib, "osgd.lib")
#pragma comment(lib, "osgDBd.lib")
#pragma comment(lib, "osgUtild.lib")
#pragma comment(lib, "osgGAd.lib")
#pragma comment(lib, "osgViewerd.lib")
#pragma comment(lib, "osgTextd.lib")

float randomValue(float min, float max)
{
    return (min + (float)rand() / (RAND_MAX + 1.0f) * (max - min));
}

osg::Vec3 randomVector(float min, float max)
{
    return osg::Vec3(randomValue(min, max),
        randomValue(min, max),
        randomValue(min, max));
}

osg::Matrix randomMatrix(float min, float max)
{
    osg::Vec3 rot = randomVector(-osg::PI, osg::PI);
    osg::Vec3 pos = randomVector(min, max);
    return osg::Matrix::rotate(rot[0], osg::X_AXIS, rot[1], osg::Y_AXIS, rot[2], osg::Z_AXIS) *
        osg::Matrix::translate(pos);
}

#define MERGE_GEOMETRY  // Comment this to disable merging geometries

#ifndef MERGE_GEOMETRY

osg::Node* createTiles(unsigned int cols, unsigned int rows)
{
    osg::ref_ptr<osg::Geode> geode = new osg::Geode;
    for (unsigned int y = 0; y < rows; ++y)
    {
        for (unsigned int x = 0; x < cols; ++x)
        {
            osg::Vec3 center((float)x, 0.0f, (float)y);

            osg::ref_ptr<osg::Vec3Array> va = new osg::Vec3Array(4);
            (*va)[0] = center + osg::Vec3(-0.45f, 0.0f, -0.45f);
            (*va)[1] = center + osg::Vec3(0.45f, 0.0f, -0.45f);
            (*va)[2] = center + osg::Vec3(0.45f, 0.0f, 0.45f);
            (*va)[3] = center + osg::Vec3(-0.45f, 0.0f, 0.45f);

            osg::ref_ptr<osg::Vec3Array> na = new osg::Vec3Array(1);
            na->front() = osg::Vec3(0.0f, -1.0f, 0.0f);

            osg::ref_ptr<osg::Vec4Array> ca = new osg::Vec4Array(1);
            ca->front() = osg::Vec4(randomVector(0.0f, 1.0f), 1.0f);

            osg::ref_ptr<osg::Geometry> geom = new osg::Geometry;
            geom->setVertexArray(va.get());
            geom->setNormalArray(na.get());
            geom->setNormalBinding(osg::Geometry::BIND_OVERALL);
            geom->setColorArray(ca.get());
            geom->setColorBinding(osg::Geometry::BIND_OVERALL);
            geom->addPrimitiveSet(new osg::DrawArrays(GL_QUADS, 0, 4));
            geode->addDrawable(geom.get());
        }
    }
    return geode.release();
}

#else

osg::Node* createTiles(unsigned int cols, unsigned int rows)
{
    unsigned int totalNum = cols * rows, index = 0;
    osg::ref_ptr<osg::Vec3Array> va = new osg::Vec3Array(totalNum * 4);
    osg::ref_ptr<osg::Vec3Array> na = new osg::Vec3Array(totalNum);
    osg::ref_ptr<osg::Vec4Array> ca = new osg::Vec4Array(totalNum);

    osg::ref_ptr<osg::Geometry> geom = new osg::Geometry;
    geom->setVertexArray(va.get());
    geom->setNormalArray(na.get());
    geom->setNormalBinding(osg::Geometry::BIND_PER_PRIMITIVE_SET);
    geom->setColorArray(ca.get());
    geom->setColorBinding(osg::Geometry::BIND_PER_PRIMITIVE_SET);

    for (unsigned int y = 0; y < rows; ++y)
    {
        for (unsigned int x = 0; x < cols; ++x)
        {
            unsigned int vIndex = 4 * index;
            osg::Vec3 center((float)x, 0.0f, (float)y);
            (*va)[vIndex + 0] = center + osg::Vec3(-0.45f, 0.0f, -0.45f);
            (*va)[vIndex + 1] = center + osg::Vec3(0.45f, 0.0f, -0.45f);
            (*va)[vIndex + 2] = center + osg::Vec3(0.45f, 0.0f, 0.45f);
            (*va)[vIndex + 3] = center + osg::Vec3(-0.45f, 0.0f, 0.45f);

            (*na)[index] = osg::Vec3(0.0f, -1.0f, 0.0f);
            (*ca)[index] = osg::Vec4(randomVector(0.0f, 1.0f), 1.0f);
            geom->addPrimitiveSet(new osg::DrawArrays(GL_QUADS, vIndex, 4));
            index++;
        }
    }

    osg::ref_ptr<osg::Geode> geode = new osg::Geode;
    geode->addDrawable(geom.get());
    return geode.release();
}

#endif

int main(int argc, char** argv)
{
	//创建Viewer对象,场景浏览器
	osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer();

	osg::ref_ptr<osg::Group> root = new osg::Group();

	//添加到场景
	root->addChild(createTiles(300, 300));

    viewer->setSceneData(root.get());

    viewer->addEventHandler(new osgViewer::StatsHandler);
    viewer->addEventHandler(new osgViewer::WindowSizeHandler());

	viewer->realize();

	viewer->run();

	return 0;
}

通过定义 MERGE_GEOMETRY 来开启优化。

3、OSG中的合并工具

OSG有个类叫做osgUtil::Optimizer,大家打开后就发现里面有好多的优化都在里面,其中就有:MERGE_GEOMETRY,当我们使用如下语句时,正常的就会将结点的Geometry进行合并:

 osgUtil::Optimizer optimizer;
 optimizer.optimize(loadedModel.get());

看其内部使用了一个工具类的方法叫做:

MergeGeometryVisitor mgv(this);
mgv.setTargetMaximumNumberOfVertices(10000);
node->accept(mgv);

它的思想也很简单,先把Group给一级一级合,然后多个Geometry合成一样。能合并的PrimitiveSet也者合并。

osgUtil::Optimizer只能进行一些通用的合并。我们理解了思想之后就可以手动的或者自己针对自己的场景写个性化的工具,以免不想合的被合了,想合的合不了。

标签:Vec3,Geometry,几何体,geom,OSG,new,0.45,osg,加载
来源: https://blog.csdn.net/m0_37251750/article/details/118488066

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有