osg3.6.5 osgEarth3.2中,鼠标操作地球放大、缩小、旋转发生屏闪

osg系列文章目录

前言

osg3.6.5 osgEarth3.2中,鼠标操作地球放大、缩小、旋转发生屏闪,如下图所示,感觉晃眼睛,这谁能忍?
在这里插入图片描述

一、分析原因

1.垂直同步(VSync)未启用:
如果垂直同步未启用,图形的刷新速率可能和显示器的刷新速率不同步,导致屏幕撕裂和闪烁。
解决方法:无效

typedef BOOL(WINAPI* PFNWGLSWAPINTERVALEXTPROC)(int interval);
PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT = nullptr;
wglSwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC)wglGetProcAddress("wglSwapIntervalEXT");
if (wglSwapIntervalEXT)
{
   
   
    wglSwapIntervalEXT(1); // Enable VSync
}

2.双缓冲(Double Buffering)未启用:
双缓冲可以避免在渲染过程中直接绘制到屏幕上,从而减少屏幕闪烁。
解决方法:无效

osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;
traits->doubleBuffer = true;

3.绘制循环中的重复绘制:
如果绘制循环中存在不必要的重复绘制操作,可能会导致性能问题和屏幕闪烁。
解决方法:无效

void COSGObject::Render(void* ptr)
{
   
   
    COSGObject* osg = static_cast<COSGObject*>(ptr);
    if (!osg)
    {
   
   
        std::cerr << "Error: osg is nullptr!" << std::endl;
        return;
    }
    osgViewer::Viewer* viewer = osg->GetViewer();
    if (!viewer)
    {
   
   
        std::cerr << "Error:viewer is nullptr!" << std::endl;
        return;
    }
    while (!viewer->done())
    {
   
   
        osg->PreFrameUpdate();
        viewer->frame();
        osg->PostFrameUpdate();
    }
    _endthread();
}

4.图形驱动程序或硬件问题:
图形驱动程序或硬件问题也可能导致屏幕闪烁。
更新过显卡驱动:无效

5.透明度和混合设置问题:
透明度和混合设置不当可能会影响渲染性能,导致屏幕闪烁。
解决方法:无效

osg::ref_ptr<osg::BlendFunc> blendFunc = new osg::BlendFunc;
blendFunc->setFunction(osg::BlendFunc::SRC_ALPHA, osg::BlendFunc::ONE_MINUS_CONSTANT_ALPHA);
stateSet->setAttributeAndModes(blendFunc, osg::StateAttribute::ON);
stateSet->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);

6.窗口重绘频率过高:
窗口重绘频率过高可能导致屏幕闪烁。
解决方法:无效

m_viewer->setUpThreadingModel(osgViewer::Viewer::SingleThreaded);

二、最终解决方法

透明对象需要特别的处理来保证它们以正确的顺序进行渲染(通常是从远到近),以避免混合错误。这行代码将该节点及其子节点放入一个专门的渲染通道(Render Bin)中,以确保正确处理透明度。
显式地设置了渲染通道的详细信息。

//启动混合
osg::ref_ptr<osg::BlendFunc> blendFunc = new osg::BlendFunc;
blendFunc->setFunction(osg::BlendFunc::SRC_ALPHA, osg::BlendFunc::ONE_MINUS_CONSTANT_ALPHA);
stateSet->setAttributeAndModes(blendFunc, osg::StateAttribute::ON);

stateSet->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF | osg::StateAttribute::OVERRIDE);


//启动透明度写入
stateSet->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
stateSet->setRenderBinDetails(0, "RenderBin");

三、完整代码

1.头文件

#pragma once

#include <osg/Group>
#include <osg/CullFace>
#include <osg/BlendFunc>
#include <osgviewer/Viewer>
#include <osgDB/ReadFile>
#include <osgviewer/api/Win32/GraphicsWindowWin32>
#include <osgGA/TrackballManipulator>
#include <osgEarth/MapNode>
#include <osgEarth/Utils>
#include <osgEarth/EarthManipulator>
#include <osgEarth/SkyView>
#include <osgEarth/Units>
//#include <osgEarth/Util/SkyNode> // 确保包含 SkyNode 的定义
#include <osgEarth/Sky>
#include <osgEarth/Ephemeris>
#include <osgEarth/ImageLayer>
#include <osgEarth/AnnotationUtils>

#include <osgText/Text>
#include <osgEarth/GeoTransform>
#include <osgEarth/AnnotationNode>
#include <osgEarth/MapInfo>
#include <osgEarth/Symbol>

#include <osgEarth/GeoMath>
#include <osgEarth/SpatialReference>
#include <osgEarth/TextSymbol>
#include <osgEarth/Feature>
#include <osgEarth/PlaceNode>
#include <osgEarth/Style>
#include <osgEarth/OGRFeatureSource>
#include <osgEarth/FeatureModelLayer>
#include <osgEarth/FeatureImageLayer>

#include <mutex>
#include <memory>
#include <tuple>

#include "CLabelTools.h"

using namespace osgEarth;
using namespace osgEarth::Util;

class COSGObject
{
   
   
public:
	COSGObject(HWND hWnd);
	~COSGObject();

	void InitOSG();
	void InitSceneGraph();
	void InitCameraConfig();
	void PreFrameUpdate();
	void PostFrameUpdate();
	static void Render(void* ptr);
	void InitOsgEarth();

	osgViewer::Viewer* GetViewer();

	void setChinaBoundariesOpacity(double opt);
	double getChinaBoundariesOpacity();

	void rmvChinaBoundaryes();
	void addChinaBoundaryes();
	//新增地标
	void addLabel();

	void loadSharp();

	std::wstring MultiByteToWideChar(const std::string& str);
	std::string WideChar2MultiByte(const std::wstring& wstr);
	std::string MultiByteToUTF8(const std::string& str);
	//1:ptr COSGObject
	//2:ptr 文件名
	//3:ptr 地标数量
	static void ReadLabelThread(void* ptr);
	//static void CreateLabelThread(void* ptr);
	//void CreateLabelThread(std::shared_ptr<std::vector<void*>> params);
	static void CreateLabelThread(void* ptr);

	//static COSGObject* m_osg;

	unsigned int m_processI;
	osg::ref_ptr<osg::Image> m_province;
	osg::ref_ptr<osg::Image> m_cityCenter;
	osg::ref_ptr<osg::Image> m_city;
	osg::ref_ptr<osg::Image> m_countyCity;
	osg::ref_ptr<osg::Image> m_county;
	osg::ref_ptr<osg::Image> m_town;
	osg::ref_ptr<osg::Image> m_vi;
	//osgEarth::Style m_style;

	std::shared_ptr<std::tuple<COSGObject*, std::shared_ptr<std::string>, unsigned int>> m_shaanXiParam;
	std::shared_ptr<std::string> m_shaanXiTxt;

	std::shared_ptr<std::tuple<COSGObject*, std::shared_ptr<std::string>, unsigned int>> m_shanXiParam;
	std::shared_ptr<std::string> m_shanXiTxt;

	/*unsigned int shaanXiParam[3];
	std::string shaanXiTxt;
	
	std::string shanXiTxt;*/
	
public:
	HWND m_hWnd;
	osg::ref_ptr<osgViewer::Viewer> m_viewer;
	osg::ref_ptr<osg::Group> m_root;
	static osg::ref_ptr<osgEarth::MapNode> m_mapNode;
	osg::ref_ptr<osgEarth::EarthManipulator> m_em;
	osg::ref_ptr<osgEarth::SkyNode> m_skyNode;

	static osgEarth::Style *m_style;
	static std::mutex m_mutex;

	time_t m_nowTime;
	tm* m_tm;

	//国界线图层
	//osg::ref_ptr<osgEarth::Layer> m_chinaBoundaries;
	osg::ref_ptr<osgEarth::ImageLayer> m_chinaBoundaries;
	osg::ref_ptr<osg::Node> m_world;
	//地标
	osg::ref_ptr<osg::Group> m_earthLabel;
};


2.实现文件

#include "pch.h"
#include "COSGObject.h"
#include "DigitalEarth.h"

osg::ref_ptr<osgEarth::MapNode> COSGObject::m_mapNode;
osgEarth::Style* COSGObject::m_style = new osgEarth::Style;
std::mutex COSGObject::m_mutex;
//COSGObject* COSGObject::m_osg = nullptr;

COSGObject::COSGObject(HWND hWnd)
{
   
   
	m_hWnd = hWnd;
	//m_osg = nullptr;
	m_viewer = nullptr;
	m_root = nullptr;
	m_processI = 0;
}

COSGObject::~COSGObject() {
   
   }

void COSGObject::InitOSG()
{
   
   
	InitSceneGraph();
	InitCameraConfig();
	InitOsgEarth();
}

void COSGObject::InitSceneGraph()
{
   
   
	// osg::ref_ptr<osg::Group> rr = new osg::Group;

	try
	{
   
   
		osgEarth::initialize();
		m_root = new osg::Group;
		// m_root->addChild(osgDB::readNodeFile("../../vs2022_64bit_3rdParty_osg365_oe32/runtime/test/earthFile/china-simple.earth"));
		//启动背面剔除
		osg::ref_ptr<osg::CullFace> cullFace = new osg::CullFace(osg::CullFace::BACK);
		osg::ref_ptr<osg::StateSet> stateSet = m_root->getOrCreateStateSet();
		stateSet->setAttributeAndModes(cullFace, osg::StateAttribute::ON);
		// osg::ref_ptr<osg::Node> mp = osgDB::readNodeFile("../../vs2022_64bit_3rdParty_osg365_oe32/runtime/test/earth/TestCommon10/output.ive");

		osg::ref_ptr<osg::Node> mp = osgDB::readNodeFile("../../vs2022_64bit_3rdParty_osg365_oe32/runtime/test/earthFile/china-simple.earth");
		m_root->addChild(mp);
		// 注意:osgEarth::MapNode只能加载earth文件,加载ive会失败
		m_mapNode = dynamic_cast<osgEarth::MapNode*>(mp.get());

		//设置透明度、材质
		osg::ref_ptr<osg::Material> material = dynamic_cast<osg::Material*>(stateSet->getAttribute(osg::StateAttribute::MATERIAL));
		if (!material){
   
   
			material = new osg::Material;
			stateSet->setAttribute(material);
		}
		//设置透明度0.2
		material->setAlpha(osg::Material::FRONT_AND_BACK, 0.2f);
		//启动混合
		osg::ref_ptr<osg::BlendFunc> blendFunc = new osg::BlendFunc;
		blendFunc->setFunction(osg::BlendFunc::SRC_ALPHA, osg::BlendFunc::ONE_MINUS_CONSTANT_ALPHA);
		stateSet->setAttributeAndModes
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值