osg实现镜面成像、倒影效果

OSG 多视图 实现导航拖拽器 OSG基于多视图实现的导航器。 阅读详情

目录

2. 代码实现

3. 功能讲解

3.1. 设置地面半透明

3.2. 设置镜面倒影成像 

 3.3. 设置地面颜色

3.4. 设置相机初始位置

4. 加上纹理

5. 总结


1. 需求提出           

      平时的业务需求,有时需要实现镜面成像、倒影效果,如下:

奶牛站在绿色半透明的地砖上,从而形成倒影。 

2. 代码实现

         代码实现如下:

#include <iostream>
#include<osgViewer/Viewer>
#include<osg/ArgumentParser>
#include<osg/Group>
#include<osgDB/readFile>
#include<osg/MatrixTransform>
#include<osg/BlendFunc>
#include<osgGA/TrackballManipulator>

osg::Program* createShaderProg()
{
	std::stringstream fp;
	fp << "#version 420 compatibility\n"
		<< "\n"
		<< "void main()\n"
		<< "{\n"
		<< "   gl_FragColor = vec4(0.0, 1.0, 0.0, 0.3);\n"
		<< "}\n";
	osg::Shader* fpShader = new osg::Shader(osg::Shader::FRAGMENT, fp
		.str());

	osg::Program* program = new osg::Program;
	program->addShader(fpShader);

	return program;
}

osg::ref_ptr<osg::Geode> createGround(float cowBoundRadius)
{
	osg::ref_ptr<osg::Geode> spGeode = new osg::Geode;

	osg::ref_ptr<osg::Geometry>spGeometry = new osg::Geometry;
	spGeode->addChild(spGeometry);

	auto maxPos = 3.5 * cowBoundRadius;

	auto pVertVarray = new osg::Vec3dArray();
	pVertVarray->push_back(osg::Vec3d(-maxPos, -maxPos, -cowBoundRadius));      // 左前
	pVertVarray->push_back(osg::Vec3d(maxPos, -maxPos, -cowBoundRadius));       // 右前
	pVertVarray->push_back(osg::Vec3d(maxPos, maxPos, -cowBoundRadius));      // 左后
	pVertVarray->push_back(osg::Vec3d(-maxPos, maxPos, -cowBoundRadius));       // 右后

	spGeometry->setVertexArray(pVertVarray);
	spGeometry->addPrimitiveSet(new osg::DrawArrays(GL_QUADS, 0, pVertVarray->size()));
	
    spGeode->getOrCreateStateSet()->setMode(GL_BLEND, osg::StateAttribute::ON);
	osg::BlendFunc* pBlendFun = new osg::BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	spGeode->getOrCreateStateSet()->setAttributeAndModes(pBlendFun, osg::StateAttribute::ON);
	
// 采用着色器来涂色
	spGeometry->getOrCreateStateSet()->setAttributeAndModes(createShaderProg(), osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE | osg::StateAttribute::PROTECTED);
	
	return spGeode;

}


int main(int argc, char *argv[])
{
	osg::ref_ptr<osg::Group> spRoot = new osg::Group;

	auto spCow = osgDB::readRefNodeFile("cow.osg");
	if (nullptr == spCow)
	{
		OSG_WARN << "node is null";
		return 1;
	}

	spRoot->addChild(spCow);

	// 绘制镜子,奶牛站在地面上
	auto groundPos = 6.85;                // 这个值是反复微调出来的
	auto pGeode = createGround(3.5);      // 这个值是反复微调出来的
	spRoot->addChild(pGeode);

	osg::ref_ptr<osg::MatrixTransform> spMatrixTran = new osg::MatrixTransform;
	spMatrixTran->setMatrix(osg::Matrix::scale(1.0, 1.0, -1.0) * osg::Matrix::translate(0.0, 0.0, -groundPos)); // 注意:必须先缩放再平移,-1表示沿着z轴镜面成像
	
	spMatrixTran->addChild(spCow);  // 奶牛倒影

	spRoot->addChild(spMatrixTran);

	osg::ref_ptr<osg::MatrixTransform> spRootMatrixTran = new osg::MatrixTransform;
	spRootMatrixTran->setMatrix(osg::Matrix::rotate(osg::DegreesToRadians(30.0), osg::Vec3(1, 0, 0))); // 沿着X轴旋转30°,便于观察
	spRootMatrixTran->addChild(spRoot);

	osgViewer::Viewer viewer;

	osg::Vec3d              _homeEye(0.0, -48.0, 0.0);// -48是反复微调出来的
	osg::Vec3d              _homeCenter(0.0, 0.0, 0.0);
	osg::Vec3d              _homeUp(0.0, 0.0, 1.0);
	viewer.setCameraManipulator(new osgGA::TrackballManipulator());
	viewer.getCameraManipulator()->setHomePosition(_homeEye, _homeCenter, _homeUp);

	viewer.setSceneData(spRootMatrixTran);
	viewer.run();
}

3. 功能讲解

       要实现镜面成像、实现倒影效果,最重要的是要实现如下3点:

  • 开启混合功能,设置混合功能因子。
  • 通过osg::Matrix::scale,在成像方向上设置缩放值为-1。
  • 将目标颜色的alpha设置为小1的某个值,具体值可进行反复微调,直到结果满意时位置。这里的目标是地面。

3.1. 设置地面半透明

       在createGround函数创建地表面时,利用如下代码开启混合功能,并分别设置源图像(即将要绘制的图像)和目标图像(帧缓冲区中的存放的图像)RGB颜色值的混合因子为GL_SRC_ALPHA和GL_ONE_MINUS_SRC_ALPHA。

spGeode->getOrCreateStateSet()->setMode(GL_BLEND, osg::StateAttribute::ON);

// 设置混合因子,测试发现,不要这两行代码也行,估计osg内部默认的混合因子是GL_SRC_ALPHA, 和GL_ONE_MINUS_SRC_ALPHA吧
osg::BlendFunc* pBlendFun = new osg::BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
spGeode->getOrCreateStateSet()->setAttributeAndModes(pBlendFun, osg::StateAttribute::ON);

本例子将混合因子设置为GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA。关于这两个值的含义及glBlendFunc(osg::BlendFunc内部其实调用的就是glBlendFunc)的作用,在任何一本讲述OPenGL的书中都会提到,请自己查阅。个人觉得将混合讲的比较好的是下列链接中的文章,可以参考:

LearnOpenGL - Blending

3.2. 设置镜面倒影成像 

        osg::Matrix::scale实现对物体缩放。大多数情况下,在x、y、z轴缩放方向上,传入正值。传入负数表示以指定方向镜面成像,也即镜像。镜像也叫反射,是一种变换,其作用是物体沿着直线(2D中)或平面(3D中)翻折,如下为沿着2D中的轴镜像效果:

 3.3. 设置地面颜色

            本例设置地面颜色的通过着色器来设置的,为了是练习osg中怎么调用着色器及如何着色器编程,也可以通过非着色器实现,代码如下:

    auto pColorArray = new osg::Vec4Array();
	pColorArray->push_back(osg::Vec4f(0.0, 1.0, 0.0, 0.3));
	spGeometry->setColorArray(pColorArray, osg::Array::Binding::BIND_OVERALL);

3.4. 设置相机初始位置

当去掉如下设置相机初始位置代码时:

    osg::Vec3d              _homeEye(0.0, -48.0, 0.0);
	osg::Vec3d              _homeCenter(0.0, 0.0, 0.0);
	osg::Vec3d              _homeUp(0.0, 0.0, 1.0);
	viewer.setCameraManipulator(new osgGA::TrackballManipulator());
	viewer.getCameraManipulator()->setHomePosition(_homeEye, _homeCenter, _homeUp);

场景离得很远,看起来很小,如下:

上述代码是将相机设置得离场景近些,这样看起来场景中的奶牛大些。如下代码不能实现这样的功能:

    osg::Vec3d              _homeEye(0.0, -48.0, 0.0);
	osg::Vec3d              _homeCenter(0.0, 0.0, 0.0);
	osg::Vec3d              _homeUp(0.0, 0.0, 1.0);
    viewer.getCamera()->setViewMatrixAsLookAt(_homeEye, _homeCenter, _homeUp);

4. 加上纹理

将地板加上纹理,会显得更逼真些,像如下的效果:

相关代码可查看利用GLSL和OSG进行三维渲染项目实战 博文。 

5. 总结

          通过这个例子,需要掌握如下技术点:

  • osg如何实现透明、半透明效果。
  • 通过osg::Matrix::scale实现镜像。
  • osg着色器编程。
  • 操作相机,以改变相机离场景的距离,从而使场景中的物体看起来更大或更小。

利用GLSL和OSG进行三维渲染项目实战 阅读详情

相关推荐

osg中运用Shader(osg初级篇2)

关于shader的概念,可以参见我的另一篇博客《opengl版本发展史及各种概念的厘清》,这里列举一个例子,用来实现一个特效,屏幕的左半部显示为红色。首先我们准备好两个shader程序: static const char* gl3_VertexShader = { "#version 330 core\n" "in vec4 osg_Vertex;\n" "in vec4 osg_Color;\n" "in vec4 osg_MultiTexCoord0;\n"

小阳明的专栏 3832

osg中漫游器的原理(一)

对osg中漫游器的解析,从中可以了解到漫游器的添加、更新、处理和自定义自己漫游器的方式

Frank的专栏 1万+

osgEarth的Rex引擎原理分析(三十四)资源释放器子节点的作用

目标:(十二)中的问题19 资源释放器器子节点在rex引擎的setMap中创建,用于释放过期对象的opengl资源 osgEarthDrivers/engine_rex/RexTerrainEngineNode.cpp void RexTerrainEngineNode::setMap(const Map* map, const TerrainOptions&amp; options) { ...

hankern的专栏 1002

osg::BlendFunc

osg::BlendFunc介绍      混合是什么呢?混合就是把两种颜色混在一起。具体一点,就是把某一像素位置原来的颜色和将要画上去的颜色,通过某种方式混在一起,从而实现特殊的效果。      假设我们需要绘制这样一个场景:透过红色的玻璃去看绿色的物体,那么可以先绘制绿色的物体,再绘制红色玻璃。在绘制红色玻璃的时候,利用“混合”功能,把将要绘制上去的红色和原来的绿色进行混合,于是得到一种新

boqing的专栏 4356

图像拼接实现镜面效果 opencv完整代码 实现(附实验结果)

一、问题重述 对一张图片进行镜面处理,最后实现左右对称,上下对称。 二、实现结果 1.原图: 2.实现结果:左右对称 3.实现结果:上下对称 三、实例代码 运行环境:Windows7,OpenCV2.3,VS2010 #include #include #include #include #include #include #incl

野草志 4750

OSG 半透明效果

OSG 半透明效果

dayuhaitang1的博客 543

osg操纵器解析

转载自:http://lzchenheng.blog.163.com/blog/static/8383353620106710534514/  osg操纵器是我们实现场景漫游的主要手段,osg提供了驾驶操纵器、飞行操纵器、轨迹球操纵器等,这些操纵器的基类为osgGA::MatrixManipulator,有时为了漫游的需要,我们需要编写自己的操纵器,要想编写好自己的操纵器,必须对osg操

luffv的专栏 4111

TMS-EEG数据预处理:eeglab工具包TESA(一)

b. 自动选择:Tools -> Reject data epochs -> Reject by probability,然后进行Plot -> channel,进行删除。TMS-EEG(经颅磁刺激-脑电图)是一种结合了TMS和EEG记录的技术,这种技术允许研究者在非侵入的情况下探测大脑环路,评估大脑的兴奋性和连通性等皮层特性。对移除脉冲伪迹的数据进行插值:Tools ->TESA -> Interpolate removed data;插值后,画图查看:数据会有数值;

weixin_43604817的博客 1496

Osg中着色器基本应用

参考资料:https://www.cnblogs.com/brainworld/p/7445290.html https://blog.youkuaiyun.com/panda1234lee/article/details/51970893 1.首先,我们需要打开osg的渲染状态节点osg::StateSet中对应的着色器模式。 osg::ref_ptr<osg::Program> p...

qq_31577553的博客 2877

Reeds-Shepp曲线公式推导及代码实现-第三部分(共三部分)

根据原始起点的坐标和航向,将上一小节计算出来的局部进行整体的平移和旋转(与归一化的步骤刚好相反),最终得到全局路径的轨迹。根据计算出来的路径,选择路径最短的轨迹(也可根据我们实际的需要定制选优规则),作为最终的轨迹输出。Reeds-Shepp曲线公式推导及代码实现-第一部分(共三部分)Reeds-Shepp曲线公式推导及代码实现-第二部分(共三部分)的值进行等步长插值,得到每段轨迹对应的生成一系列插值距离列表。根据上一步生成的插值距离列表的值,计算其对应的局部位姿值。后,我们需要根据字段类型(

jianmo的博客 1089

(Cascade extended state observer)级联ADRC的simulink仿真和程序---送给中国研究学者的精华版

(Cascade extended state observer)级联ADRC的simulink仿真和程序---送给中国研究学者的精华版

weixin_44312889的博客 3785

OSG的混合方程

2019独角兽企业重金招聘Python工程师标准>>> ...

weixin_34064653的博客 579

红外图像处理实战:用MATLAB实现时域高通滤波(THPF)去噪(附完整代码)

本文详细介绍了如何利用MATLAB实现时域高通滤波(THPF)算法进行红外图像去噪,包括核心原理、工程实现要点和完整代码示例。通过分析时间窗口选择、空域预处理优化和自适应参数调整等关键点,帮助开发者有效抑制固定图案噪声,适用于无人机载红外监测和安防监控等场景。

weixin_42783709的博客 183

OSG仿真案例(4)——创建烟雾粒子效果

创建烟雾的例子效果,并附在飞机上; #include <osgParticle/PrecipitationEffect> #include <osgParticle/Particle> #include <osgParticle/LinearInterpolator> #include <osgParticle/ParticleSystem> #...

Rexinx博客 1285

别再到处找资源了!WinCC 7.5 SP2官方下载与Windows 10保姆级安装避坑指南

本文提供了WinCC 7.5 SP2在Windows 10上的官方下载与安装全流程指南,重点解决了资源获取难、系统兼容性问题及分卷压缩处理等常见痛点。通过详细的步骤和实用技巧,帮助用户顺利完成安装并优化配置,适用于工控领域的学习者和从业者。

weixin_32924297的博客 489

pgpool-II踩坑日记两则

最近结合pgpool-II进行postgreSQL高可用的部署,过程非常煎熬,作为新手,公司也没有前辈熟悉postgreSQL,只能自己摸索。好在已经搞明白了,把困扰我很长时间的两个问题分享一下。 1. show pool_nodes 第一个问题就是 show pool_nodes 的使用,照着教程建好后,在哪里执行这个指令呢?我在pg服务器上怎么执行这个指令都显示 ERROR: unrecognized configuration parameter "pool_nodes",一度怀疑人生。翻阅了很多资料

zhaizhai6_6的博客 4540

OSG-渲染状态、纹理映射(一)

osg(OpenSceneGraph) 渲染状态、纹理映射 osg::StateSet 类 osg::StateAttribute 渲染状态(ClipeNode) 纹理映射(Texture2D、Texture3D) 多重纹理映射

liangfei868的博客 2938

opencv 双目摄像头拍照(分别左右镜头拍照)

准备一个usb线的双目同步摄像头: 运行环境是vc2015,opencv3.1。 将左右两个摄像头拍到的图片分别保存起来。 1)适用条件 双目同步摄像头(两个镜头,共用一个设备ID) 使用语言:C++ 、opencv库 摄像头 分辨率2560*960 或以上。 源程序: #include"stdafx.h" #include<iostream&g...

黎国溥 1万+

OSG使用OpenGL顶点着色器和片元着色器

目的:使用OpenGL着色语言中的顶点和片元着色器,替代原有的固化函数管道的光照和材质计算,用于场景图形中的节点选择。(砖块着色器程序来自3DLabs) ------------------------------------ 概述:OpenGL着色语言允许程序员编写自己的像素和顶点着色器。有关着色语言的更多信息,包括最低的硬件和软件需求,请参阅:http://develop

痞子龙3D编程 6732

手把手教你学Simulink--基于新型通信技术集成的场景实例:无人机利用激光通信实现高速率数据传输

摘要: 本文基于Simulink搭建无人机激光通信仿真系统,解决传统射频通信带宽不足问题。系统通过五层架构(发射机、信道、PAT系统、接收机、性能分析)实现Gbps级高速传输,重点建模大气衰减(雾/雨)、光束发散、PAT精跟踪(Stateflow+PID控制)等核心模块。仿真结果显示:晴天链路可达2.5Gbps(BER 1e-8),浓雾下链路中断,验证了雾是主要性能限制因素。案例涵盖调制方式选择、动态环境仿真及3D可视化,为无人机高速数据传输提供可扩展的仿真框架,并指出混合FSO/RF、AI-PAT等优化方

MHD0815的博客 181

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

osgFX扩展库-刻线特效、立方图镜面高光特效(2)

osgFX扩展库- 刻线特效、立方图镜面高光特效 osgFX::SpecularHighlights osgFX::Scribe

liangfei868的博客 1419

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

osg中漫游器的原理——osgGA::CameraManipulator(二)

osgGA库中所有漫游器的基类是CameraManipulator,本文就对这个类进行一个完整的解析。通过之前的分析(详细请参考这一些列的第一篇),可以知道为了实现一个自定义的漫游器,我们至少需要实现以下几个纯虚函数: virtual void setByMatrix(const osg::Matrixd& matrix) = 0; //设置相机的位置姿态矩阵 virtual void setByInverseMatrix(const osg::Matrixd& matri...

whl0071的专栏 2189

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

9.osg中实现半透明效果:

在为球贴图的基础上,实现模拟地球的透明展示。 是先前效果如下: 实现后效果如下: 实现代码如下,主要是在状态集中进行设置: osg::ref_ptrblendFunc = new osg::BlendFunc();     blendFunc->setSource(osg::BlendFunc::SRC_ALPHA);     blendFunc->setDestination

u012951394的专栏 2481

OSG新版GLSL语法全解析

OSG(OpenSceneGraph)中使用的GLSL着色器语法随着OpenGL版本更新而改变,但OSG本身语法保持不变。本文系统总结了GLSL 3.30+的新语法特性与OSG集成方式,包括:1)GLSL在OSG中的使用结构;2)新版语法对比(顶点输入、输出、uniform等);3)OSG与GLSL的内置变量映射;4)顶点/片元着色器模板;5)OSG Uniform类型对应关系;6)开发技巧(版本一致、输入绑定、调试等);7)现代OSG Shader开发框架。重点指出新版GLSL废弃了固定管线变量,需使用自

警警的博客 872

重写osgGA::TrackballManipulator实现osg的三视图

重写 osgGA::TrackballManipulator的三视图类 osgGA::StandardManipulator的home函数实现了视图恢复到默认位置(默认空格键)即正视图,在自己的继承类中实现箭头按键控制左右侧视图,俯视图。   继承关系如下图:  osgGA::GUIEventHandler -&gt;  osgGA::CameraManipulator  -&gt;...

a_Treasure的博客 4970

Array王锐力作:osg与PhysX结合系列内容——第5节 角色动画效果(下)

〖Array王锐大神力作〗osg与PhysX结合系列内容——角色动画效果(下)角色动作的过渡切换角色动画高级技巧构建测试场景并运行数据驱动的角色运动 角色动作的过渡切换 我们在研究下一步的高级角色动作之前,先看一下ozz的角色运动更新机制,这样也可以为我们后续“魔改”这个引擎的内部逻辑打下更好的基础。 ozz的动画更新流程主要分为下面四个步骤: 动画数据的采样:即根据上一帧到这一帧的时间间隔,计算动画应该经过的时间,进而从关键帧插值解算出每个关节点的局部坐标。 多个动画的融合:将多个动画采样的结果按照独立

一切皆可视 1997
上一篇: Qt Example各例子技术点说明(六)
下一篇: GLSL内置变量和内置函数
荆楚闲人
博客等级 码龄20年 3万+粉丝 473原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值