OSG学习:纹理映射(六)——灯光

以下内容来自: 

1、《OpenSceneGraph三维渲染引擎编程指南》肖鹏 刘更代 徐明亮 清华大学出版社 
2、《OpenSceneGraph三维渲染引擎设计与实践》王锐 钱学雷 清华大学出版社

3、自己的总结

创建C++项目后,首先需要配置OSG环境,具体步骤看OSG学习:WIN10系统下OSG+VS2017编译及运行第六步:新建OSG项目测试。


在场景中添加光源主要步骤为:

在渲染状态中指定场景模型的法线——在渲染状态中开启光照并允许光源——创建osg::Light对象以定义光源参数——创建光源osg::LightSource对象,将光源参数加入其中——将光源节点添加到场景图形中。

其中,需要明确的是:场景模型只有在设有单位法线时才会正确显示光照。

下面来看具体代码:

// stdafx.h

#include <osg/Node>
#include <osg/Geode>  
#include <osg/Geometry>
#include <osg/Group>

#include <osg/Camera>

#include <osg/Light> //继承自osg::StateAttribute,保存灯光的模式与属性参数信息
#include <osg/LightSource> //继承自osg::Group,灯光管理类,继承了osg::Group类的管理节点的接口,将灯光作为一个节点加入到场景图中进行渲染

#include <osg/BoundingSphere>
#include <osg/BoundingBox>

#include <osgDB/ReadFile>
#include <osgDB/WriteFile>

#include <osgViewer/ViewerEventHandlers> //事件监听
#include <osgGA/StateSetManipulator> //事件响应类,对渲染状态进行控制,按w在体/线/点模式间切换,按l在照明与非照明模式下切换,按b在是否开启背面剔除模式下切换,按t在是否开启纹理的情况下切换

#include <osgUtil/Optimizer>
#include <osgViewer/Viewer>
//.cpp

/*
在场景中添加光源:
在渲染状态中指定场景模型的法线
在渲染状态中开启光照并允许光源
创建osg::Light对象以定义光源参数
创建光源osg::LightSource对象,将光源参数加入其中
将光源节点添加到场景图形中

场景模型只有在设有单位法线时才会正确显示光照
*/

//向场景中添加光源
osg::ref_ptr<osg::Group> createLight(osg::ref_ptr<osg::Node> node)
{
	
	osg::ref_ptr<osg::StateSet> stateset = new osg::StateSet();
	
	//当光照计算结果过于明亮或者暗淡时,允许法线的重缩放
	//stateset->setMode(GL_RESCALE_NORMAL, osg::StateAttribute::ON);
	
	//场景中的缩放变换非均匀时,允许法线归一化,以保证法线为单位长度
	//stateset->setMode(GL_NORMALIZE, osg::StateAttribute::ON);
	
	//为获得光照效果允许光照,需要允许光照并至少允许一个光源
	//开启光照 将ON改为OFF则关闭光照
	stateset->setMode(GL_LIGHTING, osg::StateAttribute::ON);
	//允许一个光源GL_LIGHT0
	stateset->setMode(GL_LIGHT0, osg::StateAttribute::ON);

	//计算包围盒
	osg::BoundingSphere bs;
	node->computeBound();
	bs = node->getBound();

	//创建一个Light对象,定义光源参数
	osg::ref_ptr<osg::Light> light = new osg::Light();
	light->setLightNum(0);
	//设置方向
	light->setDirection(osg::Vec3(0.0f, 0.0f, -1.0f));
	//设置位置
	light->setPosition(osg::Vec4(bs.center().x(), bs.center().y(), bs.center().z() + bs.radius(), 1.0f));
	//设置环境光的颜色
	light->setAmbient(osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
	//设置散射光的颜色
	light->setDiffuse(osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f));

	//设置恒衰减指数
	light->setConstantAttenuation(1.0f);
	//设置线性衰减指数
	light->setLinearAttenuation(0.0f);
	//设置二次方衰减指数
	light->setQuadraticAttenuation(0.0f);

	//创建光源
	osg::ref_ptr<osg::LightSource> lightSource = new osg::LightSource();
	lightSource->setLight(light.get());

	osg::ref_ptr<osg::Group> lightRoot = new osg::Group();
	stateset = lightRoot->getOrCreateStateSet();
	lightRoot->addChild(node);
	lightRoot->addChild(lightSource.get());

	return lightRoot.get();
}

int main()
{
	osg::ref_ptr<osg::Node> node = osgDB::readNodeFile("cow.osg");
	osg::ref_ptr<osg::Group> root = new osg::Group();
	root->addChild(createLight(node.get()));

	//优化场景数据
	osgUtil::Optimizer optimizer;
	optimizer.optimize(root.get());

	osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer();
	viewer->addEventHandler(new osgGA::StateSetManipulator(viewer->getCamera()->getOrCreateStateSet()));
	viewer->setSceneData(root.get());
	viewer->realize();

	return viewer->run();
}

查看结果:

下面结果,第一个情况好是以上代码的运行结果,按l键后是第二种情况,关闭光照或开启光照但不设置光源是第三种情况。



下载完整工程OSG_14_TextureLight

猜你喜欢

转载自blog.csdn.net/u013719339/article/details/80990567