用OpenSceneGraph实现的NeHe OpenGL教程 - 第四十七课

osg学习(四十三)如何给着色器上传 更新uniform变量 glsl的片段着色器中定义两个uniform变量: uniform sampler2D tile_xyz; uniform float tile_xyzH; 在程序中: int unit; Rexter->getResources()->reserveTextureImageUnit( unit, "Tile XYZ" ); osg::Uniform* tileXYZUniform=new osg::Uniform("tile_xyz", unit); surfaceStateSet- 阅读详情
  • 简介

NeHe教程在这节课向我们介绍了Cg编程技术。Gg是nVidio公司面向GPU的语言,类似的语言还有微软的HLSL,OpenGL的GLSL,ATI的shaderMonker。关于可编程的着色语言可以在网络上找到很多的学习资源,这也是新式OpenGL的特点之一。可以预见未来随着GPU的发展,越来越多的固定管线部分可以被可编程的部分所替代。考虑到在OSG中使用GLSL比较方便,本课使用GLSL来实现。

  • 实现

在OSG中可编程的Shader部分是通过osg::Program和osg::Shader进行了封装,同时把osg::Progarm作为一种StateAttribute添加到节点之中。

首先创建网状的场景

osg::Geode*	createFlagGeode()
{
	osg::Geode* geode = new osg::Geode;
	osg::Geometry *geometry = new osg::Geometry;
	osg::Vec3Array *vertexArray = new osg::Vec3Array;
	for (int x = 0; x < SIZE - 1; x++)
	{
		for (int z = 0; z < SIZE - 1; z++)
		{
			vertexArray->push_back(osg::Vec3(mesh[x][z][0], mesh[x][z][1], mesh[x][z][2]));
			vertexArray->push_back(osg::Vec3(mesh[x+1][z][0], mesh[x+1][z][1], mesh[x+1][z][2]));
			wave_movement += 0.00001f;
			if (wave_movement > TWO_PI)
				wave_movement = 0.0f;
		}
	}
	geometry->setVertexArray(vertexArray);
	osg::PolygonMode *pm = new osg::PolygonMode(osg::PolygonMode::FRONT_AND_BACK, osg::PolygonMode::LINE);
	geometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::TRIANGLE_STRIP, 0, vertexArray->size()));
	geometry->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
	geometry->getOrCreateStateSet()->setAttributeAndModes(pm);

	osg::Uniform *uniform = new osg::Uniform("animStep", wave_movement);
	uniform->setUpdateCallback(new MoveUpdateCallback);
	geometry->getStateSet()->addUniform(uniform);
	
	osg::Shader *vertexShader = new osg::Shader(osg::Shader::VERTEX, vShader);
	osg::Shader *fragmentShader = new osg::Shader(osg::Shader::FRAGMENT, fShader);
	osg::Program *program = new osg::Program();
	program->addShader(vertexShader);
	program->addShader(fragmentShader);
	geometry->getOrCreateStateSet()->setAttributeAndModes(program);
	
	geode->addDrawable(geometry);

	return geode;
}

在OSG中Shader可以写到单独的文件中,使用osgDB::readShaderFile来读取,对于简单的shader可以直接写到字符串中:

VertexShader:

static const char*		vShader = {
	"#version 330\n"
	"in vec4 inVertex;\n"
	"uniform float animStep;\n"
	"void main(){\n"
	"vec4 tmp = inVertex;\n"
	"tmp.y = ( sin(animStep + (tmp.x / 5.0) ) + sin(animStep + (tmp.z / 4.0) ) ) * 2.5;\n"
	"gl_Position = gl_ModelViewProjectionMatrix * tmp;\n"
	"}\n"
};

FragmentShader:

static const char*		fShader = {
	"#version 330\n"
	"out vec4 fragColor;\n"
	"void main(){\n"
	"fragColor = vec4(0.5, 1.0, 0.5, 1.0);\n"
	"}\n"
};

在顶点Shader中不断的修改网状几何体的y值,形成一种类似于正弦波的效果,带代码中需要我们修改Uniform的值,让模型呈现动态的效果。

可以在Uniform的回调中完成:

class MoveUpdateCallback : public osg::Uniform::Callback
{
	virtual void operator()(osg::Uniform *uniform, osg::NodeVisitor *nv)
	{
		if(!uniform)
			return;

		float animStep;
		uniform->get(animStep);

		//按照NeHe课程中方式每帧改变64*64*0.00001
		for (int x = 0; x < SIZE - 1; x++)
		{
			for (int z = 0; z < SIZE - 1; z++)
			{
				wave_movement += 0.00001f;
				if (wave_movement > TWO_PI)
					wave_movement = 0.0f;
			}
		}		
		animStep = wave_movement;
		uniform->set(animStep);
	}
};

把节点添加到根节点下,编译运行程序:


附:本课源码(源码中可能存在错误和不足之处,仅供参考)

#include "../osgNeHe.h"

#include <QtCore/QTimer>
#include <QtGui/QApplication>
#include <QtGui/QVBoxLayout>

#include <osgViewer/Viewer>
#include <osgDB/ReadFile>
#include <osgQt/GraphicsWindowQt>

#include <osg/MatrixTransform>
#include <osg/PolygonMode>

#include <osg/Shader>
#include <osg/Uniform>
#include <osg/Program>

//////////////////////////////////////////////////////////////////////////
#define		TWO_PI 6.2831853071									
#define		SIZE	64
GLfloat		mesh[SIZE][SIZE][3];	
GLfloat		wave_movement = 0.0f;
//////////////////////////////////////////////////////////////////////////


static const char*		vShader = {
	"#version 330\n"
	"in vec4 inVertex;\n"
	"uniform float animStep;\n"
	"void main(){\n"
	"vec4 tmp = inVertex;\n"
	"tmp.y = ( sin(animStep + (tmp.x / 5.0) ) + sin(animStep + (tmp.z / 4.0) ) ) * 2.5;\n"
	"gl_Position = gl_ModelViewProjectionMatrix * tmp;\n"
	"}\n"
};

static const char*		fShader = {
	"#version 330\n"
	"out vec4 fragColor;\n"
	"void main(){\n"
	"fragColor = vec4(0.5, 1.0, 0.5, 1.0);\n"
	"}\n"
};


class MoveUpdateCallback : public osg::Uniform::Callback
{
	virtual void operator()(osg::Uniform *uniform, osg::NodeVisitor *nv)
	{
		if(!uniform)
			return;

		float animStep;
		uniform->get(animStep);

		//按照NeHe课程中方式每帧改变64*64*0.00001
		for (int x = 0; x < SIZE - 1; x++)
		{
			for (int z = 0; z < SIZE - 1; z++)
			{
				wave_movement += 0.00001f;
				if (wave_movement > TWO_PI)
					wave_movement = 0.0f;
			}
		}		
		animStep = wave_movement;
		uniform->set(animStep);
	}
};



void initialize()
{
	for (int x = 0; x < SIZE; x++)
	{
		for (int z = 0; z < SIZE; z++)
		{
			mesh[x][z][0] = (float) (SIZE / 2) - x;
			mesh[x][z][1] = 0.0f;
			mesh[x][z][2] = (float) (SIZE / 2) - z;
		}
	}
}


osg::Geode*	createFlagGeode()
{
	osg::Geode* geode = new osg::Geode;
	osg::Geometry *geometry = new osg::Geometry;
	osg::Vec3Array *vertexArray = new osg::Vec3Array;
	for (int x = 0; x < SIZE - 1; x++)
	{
		for (int z = 0; z < SIZE - 1; z++)
		{
			vertexArray->push_back(osg::Vec3(mesh[x][z][0], mesh[x][z][1], mesh[x][z][2]));
			vertexArray->push_back(osg::Vec3(mesh[x+1][z][0], mesh[x+1][z][1], mesh[x+1][z][2]));
			wave_movement += 0.00001f;
			if (wave_movement > TWO_PI)
				wave_movement = 0.0f;
		}
	}
	geometry->setVertexArray(vertexArray);
	osg::PolygonMode *pm = new osg::PolygonMode(osg::PolygonMode::FRONT_AND_BACK, osg::PolygonMode::LINE);
	geometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::TRIANGLE_STRIP, 0, vertexArray->size()));
	geometry->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
	geometry->getOrCreateStateSet()->setAttributeAndModes(pm);

	osg::Uniform *uniform = new osg::Uniform("animStep", wave_movement);
	uniform->setUpdateCallback(new MoveUpdateCallback);
	geometry->getStateSet()->addUniform(uniform);
	
	osg::Shader *vertexShader = new osg::Shader(osg::Shader::VERTEX, vShader);
	osg::Shader *fragmentShader = new osg::Shader(osg::Shader::FRAGMENT, fShader);
	osg::Program *program = new osg::Program();
	program->addShader(vertexShader);
	program->addShader(fragmentShader);
	geometry->getOrCreateStateSet()->setAttributeAndModes(program);
	
	geode->addDrawable(geometry);

	return geode;
}


class ViewerWidget : public QWidget, public osgViewer::Viewer
{
public:
	ViewerWidget(osg::Node *scene = NULL)
	{
		QWidget* renderWidget = getRenderWidget( createGraphicsWindow(0,0,640,480), scene);

		QVBoxLayout* layout = new QVBoxLayout;
		layout->addWidget(renderWidget);
		layout->setContentsMargins(0, 0, 0, 1);
		setLayout( layout );

		connect( &_timer, SIGNAL(timeout()), this, SLOT(update()) );
		_timer.start( 10 );
	}

	QWidget* getRenderWidget( osgQt::GraphicsWindowQt* gw, osg::Node* scene )
	{
		osg::Camera* camera = this->getCamera();
		camera->setGraphicsContext( gw );

		const osg::GraphicsContext::Traits* traits = gw->getTraits();

		camera->setClearColor( osg::Vec4(0.0, 0.0, 0.0, 1.0) );
		camera->setViewport( new osg::Viewport(0, 0, traits->width, traits->height) );
		camera->setProjectionMatrixAsPerspective(45.0f, static_cast<double>(traits->width)/static_cast<double>(traits->height), 0.1f, 100.0f );		
		camera->setViewMatrixAsLookAt(osg::Vec3d(0.0f, 25.0f, -45.0f), osg::Vec3d(0, 0, 0), osg::Vec3d(0, 1, 0));

		this->setSceneData( scene );

		return gw->getGLWidget();
	}

	osgQt::GraphicsWindowQt* createGraphicsWindow( int x, int y, int w, int h, const std::string& name="", bool windowDecoration=false )
	{
		osg::DisplaySettings* ds = osg::DisplaySettings::instance().get();
		osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;
		traits->windowName = name;
		traits->windowDecoration = windowDecoration;
		traits->x = x;
		traits->y = y;
		traits->width = w;
		traits->height = h;
		traits->doubleBuffer = true;
		traits->alpha = ds->getMinimumNumAlphaBits();
		traits->stencil = ds->getMinimumNumStencilBits();
		traits->sampleBuffers = ds->getMultiSamples();
		traits->samples = ds->getNumMultiSamples();

		return new osgQt::GraphicsWindowQt(traits.get());
	}

	virtual void paintEvent( QPaintEvent* event )
	{ 
		frame(); 
	}

protected:

	QTimer _timer;
};



osg::Node*	buildScene()
{
	initialize();

	osg::Group *root = new osg::Group;
	root->addChild(createFlagGeode());
	return root;
}



int main( int argc, char** argv )
{
	QApplication app(argc, argv);
	ViewerWidget* viewWidget = new ViewerWidget(buildScene());
	viewWidget->setGeometry( 100, 100, 640, 480 );
	viewWidget->show();
	return app.exec();
}

OSG中的着色器(Shader)编程 OSG 内置 Uniforms: OSG 会自动为你的着色器传递许多常用的矩阵和状态,名称是固定的。osg_NormalMatrix: 用于变换法线向量osg_FrameTime: 一个不断增加的帧时间,非常适合直接用作 uTime。osg_DepthRange: 视口的深度范围。使用获取精确时间: 上面的例子用了简单的累加。更专业的做法是在回调中使用来获取精确的时间。文件路径: 在生产项目中,最好使用来查找着色器文件,这样可以正确处理 OSG 的数据文件路径。调试。 阅读详情

相关推荐

OpenSceneGraph三维渲染引擎设计与实践

第1章 初识openscenegraph(osg). 1 1.1 场景图形初步 2 1.1.1 场景图形的概念 2 1.1.2 具体实现:三维渲染引擎 2 1.1.3 主流渲染引擎介绍 3 1.2 openscenegraph概述 4 1.2.1 诞生与发展 4 1.2.2 优势与不足 5 1.3 openscenegraph的组成结构 6 1.3.1 核心结构 6 1.3.2 资源获取 8 1.3.3 中文社区 8 第2章 osg的安装与调试 9 2.1 快速安装和使用 10 2.1.1 下载预编译包 10 2.1.2 设置环境变量 11 2.1.3 建立工程环境 13 2.1.4 范例:第一个程序 15 2.2 从源代码进行编译 16 2.2.1 osg源代码的获取与更新 16 .2.2.2 编译环境生成工具cmake 19 2.2.3 基本编译选项 22 2.2.4 高级编译选项 25 2.3 调试输入与输出 28 2.3.1 命令行输入 28 2.3.2 调试输出 29 第3章 开发预备知识 31 3.1 基本数学组件 32 3.1.1 二维与多维向量 32 3.1.2 四元数 35 3.1.3 矩阵 37 3.1.4 包围体 41 3.2 数组对象 44 3.2.1 数据数组 44 3.2.2 数据索引数组 46 3.3 内存管理机制 47 3.3.1 智能指针 48 3.3.2 参照对象 51 3.3.3 范例:智能指针的使用 52 第4章 场景的组织结构 55 4.1 节点的定义与种类 56 4.1.1 场景图形bvh树 56 4.1.2 节点的父子关系 58 4.1.3 叶节点与组节点 59 4.1.4 节点的功能与分类 62 4.2 节点的访问 65 4.2.1 访问器机制 65 4.2.2 节点的遍历函数 67 4.2.3 范例:节点属性访问器 68 4.2.4 节点的更新与事件回调 70 4.2.5 范例:使用回调实现旋转动画 71 4.3 重要节点的功能实现 74 4.3.1 空间变换节点 74 4.3.2 范例:使用空间变换节点 79 4.3.3 开关节点 81 4.3.4 范例:使用开关节点 82 4.3.5 细节层次节点(lod) 83 4.3.6 范例:使用lod节点 85 4.3.7 范例:节点代理 86 第5章 绘制几何对象与文字 89 5.1 几何元素的储存 90 5.1.1 顶点属性 90 5.1.2 顶点数组、显示列表和vbo 91 5.1.3 构建几何体对象 94 5.1.4 范例:简易房屋 100 5.2 几何元素的绘制与访问 103 5.2.1 几何体的绘制实现函数 103 5.2.2 数据的更新显示 108 5.2.3 几何体的更新回调 109 5.2.4 范例:跃动的线 110 5.2.5 信息获取和统计 112 5.2.6 范例:使用仿函数遍历几何体 113 5.3 位图的显示 116 5.3.1 图像与图像的绘制 116 5.3.2 范例:在场景中绘制位图 119 5.4 文字的显示 120 5.4.1 文字的绘制方法 120 5.4.2 文字的绘制实现函数 123 5.4.3 字符编码格式 124 5.4.4 范例:一首古诗 127 第6章 设置纹理和渲染属性 131 6.1 渲染属性与模式 132 6.1.1 opengl中的渲染状态设置 132 6.1.2 节点的渲染状态集合 132 6.1.3 渲染属性概览 135 6.2 纹理与纹理属性 139 6.2.1 纹理的实现方法 139 6.2.2 纹理的分类 143 6.2.3 范例:场景中的纹理设置 146 6.2.4 范例:纹理的明细层次(mipmap) 149 6.3 属性的实现与访问 152 6.3.1 将属性应用到场景 152 6.3.2 渲染状态集回调 153 6.3.3 范例:雾参数的实时更新 153 6.4 osg与opengl着色语言 155 6.4.1 opengl着色语言 155 6.4.2 着色器属性 159 6.4.3 一致变量回调 162 6.4.4 范例:在场景中使用glsl着色语言 162 第7章 观察我们的世界 167 7.1 场景的观察与变换 168 7.1.1 opengl中的变换 168 7.1.2 相机节点 171 7.1.3 范例:鸟瞰图相机 174 7.2 图形设备接口 176 7.2.1 图形设备与相机 176 7.2.2 窗口与像素缓存(pixel buffer) 179 7.2.3 渲染到纹理(render to texture) 181 7.2.4 范例:将场景渲染到纹理 183 7.3 视景器 186 7.3.1 视景器的主要工作 186 7.3.2 单视景器与多视景器 188 7.3.3 范例:投影墙显示 191 7.3.4 范例:多视景器系统 192 7.3.5 视景器辅助部件 194 第8章 人机交互与图形用户接口 197 8.1 获取鼠标和键盘消息 198 8.1.1 事件适配器 198 8.1.2 动作适配器 202 8.1.3 事件队列与处理器 203 8.1.4 范例:处理键盘事件.. 205 8.2 三维人机交互工具 207 8.2.1 漫游器 207 8.2.2 拖曳器 210 8.2.3 范例:场景拖曳器的实现 214 8.3 二维图形用户接口 217 8.3.1 窗口设备 217 8.3.2 windows下窗口设备的实现 219 8.3.3 范例:使用windows api构建渲染窗口 221 第9章 场景中的动画效果 225 9.1 场景动画基本组件 226 9.1.1 关键帧 226 9.1.2 采样与插值 228 9.1.3 动画频道 231 9.1.4 动画更新回调 236 9.1.5 范例:关键帧路径动画 239 9.2 刚体动画 242 9.2.1 简单路径动画 242 9.2.2 范例:使用路径动画回调 244 9.2.3 动画的多频道融合 245 9.2.4 范例:基本动画管理器 246 9.3 角色与变形动画 249 9.3.1 骨骼动画 249 9.3.2 范例:骨骼运动 252 9.3.3 变形体 255 9.3.4 范例:对折硬纸 257 9.4 渲染状态与纹理动画 259 9.4.1 渐进动画(ease motion) 259 9.4.2 范例:物体的淡入淡出 262 9.4.3 纹理动画 264 9.4.4 范例:纹理动画效果 266 第10章 文件的读写机制 269 10.1 数据文件支持机制 270 10.1.1 文件格式概述 270 10.1.2 osg支持的文件格式 272 10.1.3 基本文件读写接口 277 10.2 文件读写插件 279 10.2.1 插件的编写和注册 279 10.2.2 插件的职责链机制 283 10.2.3 文件读写回调 285 10.3 插件设计方法 287 10.3.1 范例:简单插件设计 287 10.3.2 范例:文件读取进度 290 10.4 osg(即.osg)格式及其扩展 292 10.4.1 封装器 292 10.4.2 场景扩展库插件 295 第11章 场景的动态更新与裁减 297 11.1 场景的更新流程 298 11.1.1 人机交互事件的更新 298 11.1.2 用户请求与系统调度的更新 299 11.2 场景的裁减流程 300 11.2.1 裁减的意义与常用技术 300 11.2.2 裁减访问器 303 11.2.3 状态树与状态节点 305 11.2.4 状态树的构建 309 11.2.5 裁减回调 312 11.3 数据的动态调度 313 11.3.1 动态调度技术概述 313 11.3.2 分页数据库 314 11.3.3 范例:分页lod节点 316 11.3.4 分页图像库 318 第12章 场景的多线程渲染 319 12.1 多线程开发技术概述 320 12.1.1 多线程开发的常用概念 320 12.1.2 openthreads库简介 321 12.1.3 范例:线程的创建与控制 324 12.1.4 osg操作线程 325 12.2 基本场景渲染流程 327 12.2.1 osg状态机 327 12.2.2 构建场景渲染树 333 12.2.3 渲染树的优化排序 338 12.2.4 范例:广告牌森林 339 12.3 多种线程模型的讨论与实现 341 12.3.1 渲染器与场景视图 341 12.3.2 单线程模型 347 12.3.3 多设备裁减/绘制模型 348 12.3.4 多设备绘制模型 349 12.3.5 多相机绘制模型 350 12.3.6 数据变度 351 第13章 开源社区与未来 353 13.1 基于osg的开源工程 354 13.1.1 地形与地理信息 354 13.1.2 特效实现 356 13.1.3 扩展节点组件 358 13.1.4 数据和场景管理 358 13.1.5 其他语言封装 360 13.2 开发者资源 360 13.2.1 实用网址 360 13.2.2 用户群体简介 361 13.3 十条箴言 363 主要参考资料... 365

OSG 中 常用的 Uniforms

osg中的 Uniforms主要存在两个地方,一个是SceneView中,void SceneView::updateUniforms()

UnrealEngine4 、Delta3D、OSG 3380

OsgEarth2.8 使用高程和影像

OsgEarth2.8 vs2013 Qt5.4 环境下:osgearth2.8 加载谷歌影像和高程,初级教程,

OpenSceneGraph源码分析:osgUtil模块

osgUtil(OSG Utilities)模块提供了用于场景遍历(更新、绘制)、裁剪、数据统计等公用工具。 The osgUtil library provides general purpose utility classes such as update, cull and draw traverses, scene graph operators such a scene graph optimisation, tri stripping, and tessellation. 网络资料

国产CAx(CAD/CAE/CAM)软件研发 1158

YOLOv8改进 | 融合篇,YOLOv8改进主干网络为MobileNetV3+CA注意机制+添加小目标检测层(全网独家首发,实现极限涨点)

小目标检测难点众多,导致很多算法对小目标的检测效果远不如大中型目标。影响算法性能的主要原因如下:第一,小目标分辨率低、信息量不足,导致神经网络提取到的有效特征较少。第二,小目标在图像中所占的区域较小,易受背景干扰,这对算法的定位性能要求较高。第三,小物体标注困难,训练数据有限,导致模型泛化能力差。例如多尺度学习、无锚机制和生成对抗学习等方法,都能提高小目标检测的准确性和鲁棒性。为了改善小目标漏检现象严重的问题,我在 YOLOv8 中增加了 P2 检测头,相当于有四个检测头,使网络能检测到更小的目标。

在职AI算法工程师,擅长计算机视觉,YOLO目标检测、分割等,擅长web、pyqt界面可视化,好内容持续更新中,来这里跟大家一起学习,共同进步 2858

OSG 一个简单的着色器例子

#include #include #include #include #include #include static char * vertexShader = { "varying vec4 color;\n" "void main(void ){\n" "color = gl_Vertex;\n" "gl_Position = gl_ModelViewProje

UnrealEngine4 、Delta3D、OSG 1万+

SAP FICO 内部往来对账功能开发说明书(包括测试样例、程序代码仅作参考,不保证一定可以运行)

SAP FICO 内部往来对账功能开发说明书(包括开发源代码、测试样例、FS)

我好像病了的博客 1223

OpenSceneGraph实现的NeHe OpenGL教程 - 第四十七课

简介 NeHe教程在这节课向我们介绍了Cg编程技术。Gg是nVidio公司面向GPU的语言,类似的语言还有微软的HLSL,OpenGL的GLSL,ATI的shaderMonker。关于可编程的着色语言可以在网络上找到很多的学习资源,这也是新式OpenGL的特点之一。可以预见未来随着GPU的发展,越来越多的固定管线部分可以被可编程的部分所替代。考虑到在OSG中使用GLSL比较方便,本课使用

ALLENJIAO的专栏 865

SAP Retail 补货里的 Requirement Groups,站点和商品太多时,主数据维护如何做减法

SAP Retail补货主数据设计中,Requirement Groups(需求组)是常被低估但至关重要的分类机制。它通过将具有相同补货需求的接收方(如门店)按商品分类(Merchandise Category)分组,大幅降低主数据维护量。在大型零售场景中(如800家门店、6万商品),直接维护每个门店和商品的组合参数会导致维护量失控。Requirement Groups允许企业按品类特性(如乳制品、饮料等)为不同门店组设置统一补货参数,并随业务变化灵活调整。该机制与商品分类紧密绑定,不同于MRP Group

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 68

基于Dijkstra算法的共享单车调度优化系统设计与实现

根据最新统计数据,全球共享单车市场规模已超过300亿美元,中国作为最大的共享单车市场,日订单量超过5000万次。Dijkstra算法由荷兰计算机科学家Edsger W. Dijkstra于1956年提出,用于解决带权有向图中的单源最短路径问题。本文详细介绍了基于Dijkstra算法的共享单车调度优化系统的设计与实现。本文将详细介绍基于Dijkstra算法的共享单车调度优化系统的设计与实现,采用Java 17、Spring Boot 3.x等最新技术栈。

2201_76125393的博客 618

用OpenSceneGraph实现的NeHe OpenGL教程 - 第一课

简介 OpenSceneGraph是一个开放源码,跨平台的图形开发包,它为诸如飞行器仿真,游戏,虚拟现实,科学计算可视化这样的高性能图形应用程序开发而设计。它基于场景图的概念,它提供一个在OpenGL之上的面向对象的框架,从而能把开发者从实现和优化底层图形的调用中解脱出来,并且它为图形应用程序的快速开发提供很多附加的实用工具。 NeHe教程是目前针对初学者来说最

Frank的专栏 1万+

SAP_MM模块通过CC11 创建物料版本

通过本文,我们了解了 SAP 的[SAP_MM模块通过CC11 创建物料版本]的基本概念和应用方法。当物料主数据、BOM(物料清单)、工艺路线等对象需要进行变更控制时,通过创建“版本”或“更改单”来记录、控制和追溯变更。创建完变更主记录(Change Number)后,可在物料主数据维护时引用它,从而创建物料版本化信息。,在其中可以定义物料、BOM、工艺路线等对象的变更版本信息,从而在系统中实现版本化的物料管理。

我小时候很黑的博客 816

用OpenSceneGraph实现的NeHe OpenGL教程 - 第二十四课

简介 NeHe教程在这节课中向我们介绍了如何读取显卡支持的OpenGL的扩展,如何使用Targa(TGA)图像文件作为纹理,以及如何利用OpenGL的剪裁区域来滚动屏幕文字。 在OpenInventor中没有相关的函数来获取OpenGL的扩展信息,我们只能通过直接调用OpenGL来获得这些信息。OpenInventor的纹理节点自动支持使用Targa(TGA)图像文件作为纹理,所以我们

Frank的专栏 2317

STM32CubeIDE下载程序报错:Failed to execute MI command: load G:\\Cube_IDE_EXP\\00_FIRST\\Debug\\00...如何解决??

🏆本文收录于 《全栈 Bug 调优(实战版)》 专栏。专栏聚焦真实项目中的各类疑难 Bug,从成因剖析 → 排查路径 → 解决方案 → 预防优化全链路拆解,形成一套可复用、可沉淀的实战知识体系。无论你是初入职场的开发者,还是负责复杂项目的资深工程师,都可以在这里构建一套属于自己的「问题诊断与性能调优」方法论,助你稳步进阶、放大技术价值 。

**My Coding Family** 2600

Yolov8-pose关键点检测:loss优化 | LRM loss困难样本挖掘,提升难样本、遮挡物等检测精度

LRM loss应用到能够大幅提升pose遮挡物性能

①答疑群聊服务;②YOLO大模型知识问答系统;③计算机视觉论文生成智能体; 1715

用OpenSceneGraph实现的NeHe OpenGL教程 - 第三十八课

简介 这节课NeHe教我们怎样把图片

Frank的专栏 2303

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

用OpenSceneGraph实现的NeHe OpenGL教程 - 第十一课

简介 这节课我们将创建一个以正弦波方式飘动的旗帜。本课所用到的知识在前面的课程中都有讲解,并没有什么新的内容 实现 首先创建我们的场景,关于旗帜的顶点坐标在NeHe教程中已经有非常详细的介绍,本文就不在赘述了。 float points[45][45][3]; for(int x=0; x<45; x++) { for(int y=0; y<45; y++

Frank的专栏 1579

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

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

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

OpenSceneGraph实现的NeHe OpenGL教程 - 第二十四课

简介 NeHe教程在这节课中向我们介绍了如何读取显卡支持的OpenGL的扩展,如何使用Targa(TGA)图像文件作为纹理,以及如何利用OpenGL的剪裁区域来滚动屏幕文字。osg支持tga格式的文件读取,因此不需要像NeHe课程那样解析TGA格式,有兴趣的读者可以查看osgPlugins库中的ReaderWriterTGA.cpp文件了解osg是如何读取TGA图片格式的。

ALLENJIAO的专栏 1110

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

用OpenSceneGraph实现的NeHe OpenGL教程 - 第二十五课

简介 NeHe教程在这节课中向我们介绍了如何从文件加载3D模型,并且平滑的从一个模型变换为另一个模型。两个模型之间平滑过渡的算法其实是很简单的,首先我们要保证两个模型要有相同数目的顶点,然后我们分别计算每个点从一个模型移动到另外一个模型时,中间的位置数据。我们将这个过程显示出来就会产生模型平滑过渡的效果。

Frank的专栏 1747

OpenSceneGraph实现的NeHe OpenGL教程 - 第十一课

简介 这节课我们将创建一个以正弦波方式飘动的旗帜。本课所用到的知识在前面的课程中都有讲解,并没有什么新的内容 实现 首先创建我们的场景,关于旗帜的顶点坐标在NeHe教程中已经有非常详细的介绍,本文就不在赘述了。 [cpp] view plain copy   float points[45][45][3];

ALLENJIAO的专栏 717

用OpenSceneGraph实现的NeHe OpenGL教程 - 第十二课

简介 本课NeHe教程主要是使用了OpenGL中的显示列表。OpenGL的显示列表是加速OpenGL性能的一种重要的手段。OpenGl的几何体绘制方法主要包括立即模式、顶点数组、显示列表和VBO。在OSG中显示列表是大部分OSG程序所使用的默认绘制优化行为,因此不需要我们去像OpenGL那样进行设置。 实现 首先创建整个场景,本课中我使用了OSG中预定义的几种基本形体,(os

Frank的专栏 7883

OpenSceneGraph实现的NeHe OpenGL教程 - 第三十课

简介 这节课NeHe课程实现了在场景中进行碰撞检测以及简单的物理作用(碰撞之后的反弹),碰撞检测三维图形学中一个比较高级的主题,本课只涉及了简单的规则几何体之间的碰撞检测,更复杂的实例需要读者去更深入的学习。 实现 本课中碰撞检测的算法包括线与平面的求交检测、线与圆柱体的求交、以及球体之间的碰撞检测,这些碰撞检测的原理可以参考NeHe中的介绍。 具体实现在如下几

ALLENJIAO的专栏 722

用OpenSceneGraph实现的NeHe OpenGL教程 - 第十五课

简介 NeHe这节课主要讨论OpenGL怎样给文字赋予纹理贴图。OpenGL使用glTexGen函数给文字自动生成纹理坐标。在OSG中,使用osg::TexGen这个继承自StateAttribute的类来实现相同的效果 实现 首先将创建3D的字体,代码如下: osg::Geode *fontGeode = new osg::Geode;     osg::I

Frank的专栏 1780

OpenSceneGraph实现的NeHe OpenGL教程 - 第三十二课

简介 本节课NeHe课程主要想我们介绍了OpenGL中的拾取(Selection)的方式来和场景中的物体进行交换,在OSG中并没有封装OpenGL中的拾取方式,而是用了更高效的一种方式来实现与场景中的模型进行求交的操作,对于OSG这样处理的原因可以参考OSG中的这个MailList: New to OSG, some questions (selection buffer, para

ALLENJIAO的专栏 541

用OpenSceneGraph实现的NeHe OpenGL教程 - 第二十九课

简介 这节课NeHe

Frank的专栏 1753
上一篇: 用OpenSceneGraph实现的NeHe OpenGL教程 - 第四十六课
下一篇: 用OpenSceneGraph实现的NeHe OpenGL教程 - 第四十八课
csxiaoshui
博客等级 码龄16年 873粉丝 158原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值