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

news2024/9/24 3:19:42

目录

1. 需求提出           

2. 代码实现

3. 功能讲解

3.1. 设置地面半透明

3.2. 设置镜面倒影成像 

 3.3. 设置地面颜色

3.4. 设置相机初始位置

4. 总结


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. 总结

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/710637.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

79、基于STM32单片机DHT11温湿度无线蓝牙手机APP监控报警系统(程序+原理图+PCB图+设计资料+参考论文+开题报告+元器件清单等)

摘 要 温湿度控制已成为当今社会研究的热门项目。是工农业生产过程中必须考虑的因素。作为最常见的被控参数。温度和湿度已经不再是相互独立的物理量&#xff0c;而应在系统中综合考虑。广泛应用于实验室、大棚、花圃、粮仓乃至土壤等各个领域。而传统的温湿度控制则利用湿度…

Qt QLineEdit篇

QLineEdit篇 【1】QLineEdit简介【2】QLineEdit常用方法【3】QLineEdit使用举例UI设计界面效果头文件源文件 PC饱和了&#xff0c;跟我学Qt比较实在&#xff0c;哈哈哈 【1】QLineEdit简介 QLineEdit是Qt框架中的一个类&#xff0c;用于创建一个文本输入框&#xff0c;允许用…

【WSN定位】基于蜣螂优化算法DBO的Dvhop定位算法 不同锚节点比例和不同通信半径情况下对比【Matlab代码#45】

文章目录 【可更换其他算法&#xff0c;获取资源请见文章第5节&#xff1a;资源获取】1. Dvhop定位算法2. 蜣螂优化算法3. 部分代码展示4. 仿真结果展示5. 资源获取 【可更换其他算法&#xff0c;获取资源请见文章第5节&#xff1a;资源获取】 1. Dvhop定位算法 根据距离矢量和…

#systemverilog# 关于随机约束之 约束块

随机变量的值通过由约束块声明的约束表达式来确定。像任务、函数和变量一样,随机块是类的成员。在一个类中,约束块的名字必须是唯一的。 一 语法定义 声明约束块的语法如下: (1)constraint_identifier是约束块的名字。使用constraint_mode()(参见12.8节)方法,这个名字…

初步认识Java垃圾回收算法

GCRoot指被栈上直接或间接引用的对象&#xff0c;或被本地方法栈直接或间接引用的对象&#xff0c;或被方法区引用的对象。 被引用的对象是不能被删除的。 如果对象跟GCRoot并没有直接或间接相连的关系&#xff0c;那么这些对象就可以被删除了。 标记-清理&#xff1a;将需要删…

C++智能指针使用陷阱、shared_ptr实现

一 智能指针使用概述 1.使用场景 1.1 unique_ptr 1.1.1 概念 std::unique_ptr 是通过指针占有并管理另一对象&#xff0c;并在 unique_ptr 离开作用域时释放该对象的智能指针。 std::unique_ptr 常用于管理对象的生存期&#xff0c;包含&#xff1a; 通过正常退出和经由异…

SpringBoot 实现导出数据 - EasyExcel 导出数据

文章目录 1. EasyExcel 介绍2. 导出2.1 引入依赖2.2 构建测试实体类 3. 设置单元格大小 1. EasyExcel 介绍 EasyExcel 官网介绍 传统操作Excel大多都是利用 Apach POI 进行操作的&#xff0c;但是 POI 框架并不完善&#xff0c;使用过程非常繁琐且有较多的缺陷&#xff1a; 动态…

lesson11 Zigbee MAC地址通信

目录 Zigbee MAC地址通信 前言 查看MAC地址&#xff08;含组网过程抓包分析&#xff09; 方法1&#xff1a;通过dongle抓包查看MAC地址 方法2&#xff1a;仿真调试查看MAC 实验过程 实现步骤 实验效果 出错分析 最终现象 结果分析 Zigbee MAC地址通信 前言 1、Zig…

Python中类的变量,一个下划线与两个下划线的区别

形似 功能__xx这是私有变量&#xff0c; 只有内部可以访问&#xff0c;外部不可以访问。但是也不是一定不可以访问&#xff0c;只要以 _类名__xx样式就可以访问 。但最好不要这样做&#xff0c;养成良好编程习惯_x这是实例变量&#xff0c;可以访问&#xff0c;但是不要轻…

STM32MP157-正点原子第六章tf-a使用编译错误

原因&#xff1a;交叉编译工具链选择错误 亲测&#xff1a; gcc-arm-10.3-2021.07-x86_64-arm-none-linux-gnueabihf.tar.xz 和 gcc-arm-11.2-2022.02-x86_64-arm-none-linux-gnueabihf.tar.xz 可以成功编译 下载网址https://mirrors.tuna.tsinghua.edu.cn/armbian-relea…

全国各城市交通运输邮电业本地电话用户(1999-2020年)

本数据展示了全国各城市的本地电话用户数量。通过对这些数量的分析&#xff0c;可以了解全国各城市通信设施建设的发展情况、人口密度以及工业经济的发展程度等方面的信息。此数据不仅可供政府部门制定信息技术政策&#xff0c;还可以为企业投资提供重要参考。同时&#xff0c;…

Leetcode-每日一题【382.链表随机结点】

题目 给你一个单链表,随机选择链表的一个节点,并返回相应的节点值。每个节点被选中的概率一样 。 实现 Solution 类&#xff1a; Solution(ListNode head) 使用整数数组初始化对象。int getRandom() 从链表中随机选择一个节点并返回该节点的值。链表中所有节点被选中的概率相…

网络空间安全专业未来的发展前景以及薪资待遇如何?

不管是考虑未来报读专业的准大学生&#xff0c;还是初入职场的实习生&#xff0c;亦或是想要跳槽转岗的职场人&#xff0c;当我们开始选择一份工作时&#xff0c;本质上都在考虑以下三个问题&#xff1a; 这份工作的收入水平如何&#xff1b;这份工作有没有发展前景&#xff1…

基于卷积神经网络的目标分类案例

文章目录 一、卷积神经网络二、环境配置及数据集准备三、猫狗数据分类建模1、猫狗图像预处理2、猫狗分类的实例——基准模型3、基准模型的调整 一、卷积神经网络 卷积神经网络&#xff08;Convolutional Neural Networks, CNN 是一类包含卷积计算且具有深度结构的前馈神经网络…

HashMap源码分析

文章目录 1、put方法流程2 、扩容机制3 、get方法 分析源码我们一般从三个方面入手&#xff1a; 常见属性&#xff08;成员变量&#xff09;构造方法关键方法 下面分析一下HashMap源码&#xff1a; 首先常见属性有&#xff1a; DEFAULT_INITIAL_CAPACITY 1 << 4; // a…

二叉树进阶——搜索二叉树

搜索二叉树 1. 概念2. 二叉搜索树的操作2.1 查找2.2 插入2.3 删除&#xff08;重点&#xff09; 3. 搜索二叉树的应用4. 搜索二叉树的性能分析 1. 概念 二叉搜索树又称二叉排序树&#xff0c;它或者是一棵空树&#xff0c;或者是具有以下性质的二叉树: 若它的左子树不为空&am…

《项目实战》构建前后端一体化项目查询CSDN博客Top100文章质量分

系列文章目录 构建前后端一体化项目查询CSDN博客Top100文章质量分 文章目录 系列文章目录前言1、搭建后端框架1.1、 创建RestFull风格接口1.2、创建获取数据服务1.2.1、在个人博客页&#xff0c;找到获取全部博文的路径&#xff08;页面-> network->找到加载博文的地址&…

C# ---委托机制 delegate 和 回调方法 callback

C# --- 委托机制 delegate 和 回调 callback 什么是委托机制委托机制的优点C# 中的Action 和 Func委托机制的主要用处 --- 回调 Callback 什么是委托机制 委托机制相当于C语言中的函数指针, 将一个方法的reference传入另外一个方法中 Example //创建一个方法 //创建一个委托 …

青少年机器人技术一级考试备考重点(二):基础结构与力的基础

随着机器人技术的飞速发展&#xff0c;越来越多的青少年开始关注并参与其中。青少年机器人技术考试作为一项评估学生机器人技术水平的重要考试&#xff0c;备受广大青少年和家长的关注。为了更好地备战青少年机器人技术一级考试&#xff0c;了解考试的学习要点和备考重点是非常…

设计师简历范文

设计师简历范文一&#xff1a; 姓名&#xff1a; 目前所在&#xff1a; 天河区 年  龄&#xff1a; 26 户口所在&#xff1a; 湖南 国  籍&#xff1a; 中国 婚姻状况&#xff1a; 未婚 民  族&#xff1a; 汉族 身  高&#xff1a; 170 cm 体  重&#xff1a; 65 kg…