OpenSceneGraph基础:光照

效果:

接着前篇进行(http://blog.csdn.net/boksic/article/details/44002155),现在考虑光照效果

主程序

转载请注明http://blog.csdn.net/boksic 如有疑问欢迎留言

和之前基本唯一的变化就是把窗口部分的操作放在初始化函数initCanvas里进行。

int main(int argc, const char* argv[]) {

	osg::Group *scene = startupScene();

	osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer;
	viewer->setSceneData(scene);
	initCanvas(viewer);

	while (!viewer->done()) {
		viewer->frame();
		update(0.5); // do the update advancing 500ms
	}
	return 0;
}

窗口初始化(initCanvas)

我们使用GraphicsContext类来对设备上下文进行操作,该类需要一个Traits结构来定义具体的窗口属性,例如窗口大小,窗口位置等。

void initCanvas(osg::ref_ptr<osgViewer::Viewer> viewer) {
	int x = 20;
	int y = 20;
	osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;
	traits->x = x;
	traits->y = y;
	traits->width = width;
	traits->height = height;
	if (offScreen) {
		traits->windowDecoration = false;
		traits->doubleBuffer = true;
		traits->pbuffer = true;
	}
	else {
		traits->windowDecoration = true;
		traits->doubleBuffer = true;
		traits->pbuffer = false;
	}
	traits->windowName = "http://blog.csdn.net/boksic";
	traits->sharedContext = 0;
	traits->alpha = 8;
	traits->readDISPLAY();
	traits->setUndefinedScreenDetailsToDefaultScreen();

	osg::GraphicsContext* _gc = osg::GraphicsContext::createGraphicsContext(traits.get());

	if (!_gc) {
		osg::notify(osg::NOTICE)
			<< "Failed to create pbuffer, failing back to normal graphics window." << endl;

		traits->pbuffer = false;
		_gc = osg::GraphicsContext::createGraphicsContext(traits.get());
	}

}

Viewer内置了Camera对象来控制窗口,我们可以通过getCamera函数来对该对象进行操作,例如setClearColor设置清屏颜色。

	viewer->getCamera()->setGraphicsContext(_gc);
	viewer->getCamera()->setViewport(new osg::Viewport(x, y, width, height));
	viewer->getCamera()->setClearColor(osg::Vec4(0, 0, 0, 1));

	viewer->setCameraManipulator(new osgGA::TrackballManipulator);
	viewer->setThreadingModel(osgViewer::ViewerBase::SingleThreaded);
	viewer->realize();
	viewer->setReleaseContextAtEndOfFrameHint(false);

场景初始化(startup)

首先按前篇的方法建立几何图形:

	//球
	osg::Geode *sphere = new osg::Geode();
	sphere->addDrawable(new osg::ShapeDrawable(new osg::Sphere(osg::Vec3(-2, 0, 0), 1)));
	//正方体
	osg::Geode *cube = createCube();
	cubeTransform = new osg::PositionAttitudeTransform();
	cubeTransform->addChild(cube);
	cubeTransform->setPosition(osg::Vec3(2, 0, -1));
	//金字塔
	osg::Geode *pyramid = createPyramid();
	pyramidTransform = new osg::PositionAttitudeTransform();
	pyramidTransform->addChild(pyramid);
	pyramidTransform->setPosition(osg::Vec3(5, 0, -1));

这里,球是按照osg内置函数建立模型,金子塔与之前相同,正方体则使用了setNormalBinding来绑定法向量用到了法向量(注意:与颜色索引一样,设置法线索引的setNormalIndices也已经被废除了),正方体的建立函数:

osg::Geode *createCube() {
	// vertex array
	osg::Vec3Array *vertexArray = new osg::Vec3Array();

	// bottom front left
	vertexArray->push_back(osg::Vec3(-1, -1, 0));
	vertexArray->push_back(osg::Vec3(-1, -1, 0));
	vertexArray->push_back(osg::Vec3(-1, -1, 0));
	// bottom front right
	vertexArray->push_back(osg::Vec3(+1, -1, 0));
	vertexArray->push_back(osg::Vec3(+1, -1, 0));
	vertexArray->push_back(osg::Vec3(+1, -1, 0));
	// bottom back right
	vertexArray->push_back(osg::Vec3(+1, +1, 0));
	vertexArray->push_back(osg::Vec3(+1, +1, 0));
	vertexArray->push_back(osg::Vec3(+1, +1, 0));
	// bottom back left
	vertexArray->push_back(osg::Vec3(-1, +1, 0));
	vertexArray->push_back(osg::Vec3(-1, +1, 0));
	vertexArray->push_back(osg::Vec3(-1, +1, 0));

	// top front left
	vertexArray->push_back(osg::Vec3(-1, -1, 2));
	vertexArray->push_back(osg::Vec3(-1, -1, 2));
	vertexArray->push_back(osg::Vec3(-1, -1, 2));
	// top front right
	vertexArray->push_back(osg::Vec3(+1, -1, 2));
	vertexArray->push_back(osg::Vec3(+1, -1, 2));
	vertexArray->push_back(osg::Vec3(+1, -1, 2));
	// top back right
	vertexArray->push_back(osg::Vec3(+1, +1, 2));
	vertexArray->push_back(osg::Vec3(+1, +1, 2));
	vertexArray->push_back(osg::Vec3(+1, +1, 2));
	// top back left
	vertexArray->push_back(osg::Vec3(-1, +1, 2));
	vertexArray->push_back(osg::Vec3(-1, +1, 2));
	vertexArray->push_back(osg::Vec3(-1, +1, 2));

	// face array
	osg::DrawElementsUInt *faceArray = new osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLES, 0);

	// bottom
	faceArray->push_back(0); // face 1
	faceArray->push_back(9);
	faceArray->push_back(3);
	faceArray->push_back(9); // face 2
	faceArray->push_back(6);
	faceArray->push_back(3);
	// top
	faceArray->push_back(21);  //face 3
	faceArray->push_back(12);
	faceArray->push_back(18);
	faceArray->push_back(12);  //face 4
	faceArray->push_back(15);
	faceArray->push_back(18);
	// left
	faceArray->push_back(22);  //face 5
	faceArray->push_back(10);
	faceArray->push_back(13);
	faceArray->push_back(10);  //face 6
	faceArray->push_back(1);
	faceArray->push_back(13);
	// right
	faceArray->push_back(16);  //face 7
	faceArray->push_back(4);
	faceArray->push_back(19);
	faceArray->push_back(4);  //face 8
	faceArray->push_back(7);
	faceArray->push_back(19);
	// front
	faceArray->push_back(14);  //face 9
	faceArray->push_back(2);
	faceArray->push_back(17);
	faceArray->push_back(2);   //face 10
	faceArray->push_back(5);
	faceArray->push_back(17);
	// back
	faceArray->push_back(20);  //face 11
	faceArray->push_back(8);
	faceArray->push_back(23);
	faceArray->push_back(8);   //face 12
	faceArray->push_back(11);
	faceArray->push_back(23);

	// normal array
	osg::Vec3Array *normalArray = new osg::Vec3Array();
	normalArray->push_back(osg::Vec3(0, 0, -1));
	normalArray->push_back(osg::Vec3(0, -1, 0));
	normalArray->push_back(osg::Vec3(+1, 0, 0));

	normalArray->push_back(osg::Vec3(0, 0, -1));
	normalArray->push_back(osg::Vec3(0, +1, 0));
	normalArray->push_back(osg::Vec3(+1, 0, 0));

	normalArray->push_back(osg::Vec3(0, 0, -1));
	normalArray->push_back(osg::Vec3(0, +1, 0));
	normalArray->push_back(osg::Vec3(-1, 0, 0));

	normalArray->push_back(osg::Vec3(0, 0, -1));
	normalArray->push_back(osg::Vec3(0, -1, 0));
	normalArray->push_back(osg::Vec3(-1, 0, 0));

	normalArray->push_back(osg::Vec3(0, 0, +1));
	normalArray->push_back(osg::Vec3(0, -1, 0));
	normalArray->push_back(osg::Vec3(+1, 0, 0));

	normalArray->push_back(osg::Vec3(0, 0, +1));
	normalArray->push_back(osg::Vec3(0, +1, 0));
	normalArray->push_back(osg::Vec3(+1, 0, 0));

	normalArray->push_back(osg::Vec3(0, 0, +1));
	normalArray->push_back(osg::Vec3(0, +1, 0));
	normalArray->push_back(osg::Vec3(-1, 0, 0));

	normalArray->push_back(osg::Vec3(0, 0, +1));
	normalArray->push_back(osg::Vec3(0, -1, 0));
	normalArray->push_back(osg::Vec3(-1, 0, 0));

	osg::Geometry *geometry = new osg::Geometry();
	geometry->setVertexArray(vertexArray);

	geometry->setNormalArray(normalArray);
	geometry->setNormalBinding(osg::Geometry::BIND_PER_VERTEX);
	geometry->addPrimitiveSet(faceArray);

	osg::Geode *cube = new osg::Geode();
	cube->addDrawable(geometry);
	return cube;
}

建立组节点,获取其渲染状态StateSet。StateSet保存了一系列Opengl的渲染属性和值,用于控制节点下图形的渲染,若要设置则需获取该对象的StateSet后进行操作。

StateSet *lightStateSet;
Node *startup() { 
        Group *scene = new Group();
	lightStateSet = scene->getOrCreateStateSet();
}

建立材质属性

osg的Material 封装了OpenGL 的glMaterial()和glColorMaterial(),用法基本类似。而建立Material后再关联到图形的StateSet中即可试目标图形具有该材质属性。这里为球体和正方体赋予了该材质。

	// create white material
	osg::Material *material = new osg::Material();
	material->setDiffuse(osg::Material::FRONT, osg::Vec4(1.0, 1.0, 1.0, 1.0));
	material->setSpecular(osg::Material::FRONT, osg::Vec4(0.0, 0.0, 0.0, 1.0));
	material->setAmbient(osg::Material::FRONT, osg::Vec4(0.1, 0.1, 0.1, 1.0));
	material->setEmission(osg::Material::FRONT, osg::Vec4(0.0, 0.0, 0.0, 1.0));
	material->setShininess(osg::Material::FRONT, 25.0);

	// assign the material to the sphere and cube
	sphere->getOrCreateStateSet()->setAttribute(material);
	cube->getOrCreateStateSet()->setAttribute(material);

设置光源

OSG使用Light对象来定义光源属性,Light的setLightNum函数是用来关联OpenGL的位置数GL_LIGHT0 到GL_LIGHT7的,所以需要赋予其一个唯一的值(uniqueLightNumber)。我们可以定义一个简单的光源生成函数

int uniqueLightNumber = 0;
osg::Light *createLight(osg::Vec4 color)
{
	osg::Light *light = new osg::Light();
	// each light must have a unique number
	light->setLightNum(uniqueLightNumber++);
	// we set the light's position via a PositionAttitudeTransform object
	light->setPosition(osg::Vec4(0.0, 0.0, 0.0, 1.0));
	light->setDiffuse(color);
	light->setSpecular(osg::Vec4(1.0, 1.0, 1.0, 1.0));
	light->setAmbient(osg::Vec4(0.0, 0.0, 0.0, 1.0));

	return light;
}

而Light对象需要放在LightSource的节点当中,可以通过LightSource来控制灯光的位置以及状态。

	// Create Lights - Red, Green, Blue
	osg::Vec4 lightColors[] = { osg::Vec4(1.0, 0.0, 0.0, 1.0), osg::Vec4(0.0, 1.0, 0.0, 1.0), osg::Vec4(0.0, 0.0, 1.0, 1.0) };

	osg::Group *root = new osg::Group();
	lightStateSet = root->getOrCreateStateSet();

	osg::Geode *lightMarker[LIGHTS];
	osg::LightSource *lightSource[LIGHTS];

	for (int i = 0; i < LIGHTS; i++) {
		lightMarker[i] = new osg::Geode();
		lightMarker[i]->addDrawable(new osg::ShapeDrawable(new osg::Sphere(osg::Vec3(), 1)));
		lightMarker[i]->getOrCreateStateSet()->setAttribute(createSimpleMaterial(lightColors[i]));

		lightSource[i] = new osg::LightSource();
		lightSource[i]->setLight(createLight(lightColors[i]));
		lightSource[i]->setLocalStateSetModes(osg::StateAttribute::ON);
		lightSource[i]->setStateSetModes(*lightStateSet, osg::StateAttribute::ON);

		lightTransform[i] = new osg::PositionAttitudeTransform();
		lightTransform[i]->addChild(lightSource[i]);
		lightTransform[i]->addChild(lightMarker[i]);
		lightTransform[i]->setPosition(osg::Vec3(0, 0, 5));
		lightTransform[i]->setScale(osg::Vec3(0.1, 0.1, 0.1));

		root->addChild(lightTransform[i]);
	}

最后不忘添加到组节点当中

		root->addChild(sphere);
		root->addChild(cubeTransform);
		root->addChild(pyramidTransform);

更新部分(update函数)

这里实现的是三个点光源做圆周运动

void update(float dt) {
	myTimer += 0.01*dt;
	lightTransform[0]->setPosition(osg::Vec3(cos(myTimer), sin(myTimer), 0) * 4);
	lightTransform[1]->setPosition(osg::Vec3(0, cos(myTimer), sin(myTimer)) * 4);
	lightTransform[2]->setPosition(osg::Vec3(sin(myTimer), cos(myTimer), sin(myTimer)) * 4);
}

最后附上完整代码

#include <osgGA/TrackballManipulator>
#include <osg/PositionAttitudeTransform>
#include <osgGA/GUIEventHandler>
#include <osg/Material>
#include <osg/ShapeDrawable>
osg::Geode *createCube() {
	// vertex array
	osg::Vec3Array *vertexArray = new osg::Vec3Array();

	// bottom front left
	vertexArray->push_back(osg::Vec3(-1, -1, 0));
	vertexArray->push_back(osg::Vec3(-1, -1, 0));
	vertexArray->push_back(osg::Vec3(-1, -1, 0));
	// bottom front right
	vertexArray->push_back(osg::Vec3(+1, -1, 0));
	vertexArray->push_back(osg::Vec3(+1, -1, 0));
	vertexArray->push_back(osg::Vec3(+1, -1, 0));
	// bottom back right
	vertexArray->push_back(osg::Vec3(+1, +1, 0));
	vertexArray->push_back(osg::Vec3(+1, +1, 0));
	vertexArray->push_back(osg::Vec3(+1, +1, 0));
	// bottom back left
	vertexArray->push_back(osg::Vec3(-1, +1, 0));
	vertexArray->push_back(osg::Vec3(-1, +1, 0));
	vertexArray->push_back(osg::Vec3(-1, +1, 0));

	// top front left
	vertexArray->push_back(osg::Vec3(-1, -1, 2));
	vertexArray->push_back(osg::Vec3(-1, -1, 2));
	vertexArray->push_back(osg::Vec3(-1, -1, 2));
	// top front right
	vertexArray->push_back(osg::Vec3(+1, -1, 2));
	vertexArray->push_back(osg::Vec3(+1, -1, 2));
	vertexArray->push_back(osg::Vec3(+1, -1, 2));
	// top back right
	vertexArray->push_back(osg::Vec3(+1, +1, 2));
	vertexArray->push_back(osg::Vec3(+1, +1, 2));
	vertexArray->push_back(osg::Vec3(+1, +1, 2));
	// top back left
	vertexArray->push_back(osg::Vec3(-1, +1, 2));
	vertexArray->push_back(osg::Vec3(-1, +1, 2));
	vertexArray->push_back(osg::Vec3(-1, +1, 2));

	// face array
	osg::DrawElementsUInt *faceArray = new osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLES, 0);

	// bottom
	faceArray->push_back(0); // face 1
	faceArray->push_back(9);
	faceArray->push_back(3);
	faceArray->push_back(9); // face 2
	faceArray->push_back(6);
	faceArray->push_back(3);
	// top
	faceArray->push_back(21);  //face 3
	faceArray->push_back(12);
	faceArray->push_back(18);
	faceArray->push_back(12);  //face 4
	faceArray->push_back(15);
	faceArray->push_back(18);
	// left
	faceArray->push_back(22);  //face 5
	faceArray->push_back(10);
	faceArray->push_back(13);
	faceArray->push_back(10);  //face 6
	faceArray->push_back(1);
	faceArray->push_back(13);
	// right
	faceArray->push_back(16);  //face 7
	faceArray->push_back(4);
	faceArray->push_back(19);
	faceArray->push_back(4);  //face 8
	faceArray->push_back(7);
	faceArray->push_back(19);
	// front
	faceArray->push_back(14);  //face 9
	faceArray->push_back(2);
	faceArray->push_back(17);
	faceArray->push_back(2);   //face 10
	faceArray->push_back(5);
	faceArray->push_back(17);
	// back
	faceArray->push_back(20);  //face 11
	faceArray->push_back(8);
	faceArray->push_back(23);
	faceArray->push_back(8);   //face 12
	faceArray->push_back(11);
	faceArray->push_back(23);

	// normal array
	osg::Vec3Array *normalArray = new osg::Vec3Array();
	normalArray->push_back(osg::Vec3(0, 0, -1));
	normalArray->push_back(osg::Vec3(0, -1, 0));
	normalArray->push_back(osg::Vec3(+1, 0, 0));

	normalArray->push_back(osg::Vec3(0, 0, -1));
	normalArray->push_back(osg::Vec3(0, +1, 0));
	normalArray->push_back(osg::Vec3(+1, 0, 0));

	normalArray->push_back(osg::Vec3(0, 0, -1));
	normalArray->push_back(osg::Vec3(0, +1, 0));
	normalArray->push_back(osg::Vec3(-1, 0, 0));

	normalArray->push_back(osg::Vec3(0, 0, -1));
	normalArray->push_back(osg::Vec3(0, -1, 0));
	normalArray->push_back(osg::Vec3(-1, 0, 0));

	normalArray->push_back(osg::Vec3(0, 0, +1));
	normalArray->push_back(osg::Vec3(0, -1, 0));
	normalArray->push_back(osg::Vec3(+1, 0, 0));

	normalArray->push_back(osg::Vec3(0, 0, +1));
	normalArray->push_back(osg::Vec3(0, +1, 0));
	normalArray->push_back(osg::Vec3(+1, 0, 0));

	normalArray->push_back(osg::Vec3(0, 0, +1));
	normalArray->push_back(osg::Vec3(0, +1, 0));
	normalArray->push_back(osg::Vec3(-1, 0, 0));

	normalArray->push_back(osg::Vec3(0, 0, +1));
	normalArray->push_back(osg::Vec3(0, -1, 0));
	normalArray->push_back(osg::Vec3(-1, 0, 0));

	osg::Geometry *geometry = new osg::Geometry();
	geometry->setVertexArray(vertexArray);

	geometry->setNormalArray(normalArray);
	geometry->setNormalBinding(osg::Geometry::BIND_PER_VERTEX);
	geometry->addPrimitiveSet(faceArray);

	osg::Geode *cube = new osg::Geode();
	cube->addDrawable(geometry);
	return cube;
}

osg::Geode *createPyramid(){
	// vertex array
	osg::Vec3Array *vertexArray = new osg::Vec3Array();
	vertexArray->push_back(osg::Vec3(-1, -1, 0)); // front left
	vertexArray->push_back(osg::Vec3(+1, -1, 0)); // front right
	vertexArray->push_back(osg::Vec3(+1, +1, 0)); // back right
	vertexArray->push_back(osg::Vec3(-1, +1, 0)); // back left
	vertexArray->push_back(osg::Vec3(0,0 ,  sqrt(2))); // peak
	vertexArray->push_back(osg::Vec3(0, 0, -sqrt(2))); // lower peak

	// face array
	// give indices of vertices in counter-clockwise order
	osg::DrawElementsUInt *faceArray = new osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLES, 0);
	faceArray->push_back(0); // face 0
	faceArray->push_back(1);
	faceArray->push_back(4);
	faceArray->push_back(1); // face 1
	faceArray->push_back(2);
	faceArray->push_back(4);
	faceArray->push_back(2); // face 2
	faceArray->push_back(3);
	faceArray->push_back(4);
	faceArray->push_back(3); // face 3
	faceArray->push_back(0);
	faceArray->push_back(4);
	faceArray->push_back(0); // face 4
	faceArray->push_back(5);
	faceArray->push_back(1);
	faceArray->push_back(2); // face 5
	faceArray->push_back(1);
	faceArray->push_back(5);
	faceArray->push_back(3); // face 6
	faceArray->push_back(2);
	faceArray->push_back(5);
	faceArray->push_back(0); // face 7
	faceArray->push_back(3);
	faceArray->push_back(5);

	// vertex color array
	osg::Vec4Array *colorArray = new osg::Vec4Array();
	colorArray->push_back(osg::Vec4(1.0f, 0.0f, 0.0f, 1.0f)); //index 0 red
	colorArray->push_back(osg::Vec4(0.0f, 1.0f, 0.0f, 1.0f)); //index 1 green
	colorArray->push_back(osg::Vec4(0.0f, 0.0f, 1.0f, 1.0f)); //index 2 blue
	colorArray->push_back(osg::Vec4(1.0f, 0.0f, 1.0f, 1.0f)); //index 3 purple
	colorArray->push_back(osg::Vec4(1.0f, 1.0f, 0.0f, 1.0f)); //index 4 white
	colorArray->push_back(osg::Vec4(1.0f, 1.0f, 0.5f, 1.0f)); //index 5 white

	osg::Geometry *geometry = new osg::Geometry();
	geometry->setVertexArray(vertexArray);
	geometry->setColorArray(colorArray);
	geometry->setColorBinding(osg::Geometry::BIND_PER_VERTEX);
	geometry->addPrimitiveSet(faceArray);

	osg::Geode *pyramid = new osg::Geode();
	pyramid->addDrawable(geometry);
	return pyramid;
}

int uniqueLightNumber = 0;
osg::Light *createLight(osg::Vec4 color)
{
	osg::Light *light = new osg::Light();
	// each light must have a unique number
	light->setLightNum(uniqueLightNumber++);
	// we set the light's position via a PositionAttitudeTransform object
	light->setPosition(osg::Vec4(0.0, 0.0, 0.0, 1.0));
	light->setDiffuse(color);
	light->setSpecular(osg::Vec4(1.0, 1.0, 1.0, 1.0));
	light->setAmbient(osg::Vec4(0.0, 0.0, 0.0, 1.0));

	return light;
}
osg::Material *createSimpleMaterial(osg::Vec4 color)
{
	osg::Material *material = new osg::Material();
	material->setDiffuse(osg::Material::FRONT, osg::Vec4(0.0, 0.0, 0.0, 1.0));
	material->setEmission(osg::Material::FRONT, color);

	return material;
}

int const LIGHTS = 3;
osg::PositionAttitudeTransform *cubeTransform;
osg::PositionAttitudeTransform *pyramidTransform;
osg::PositionAttitudeTransform *lightTransform[LIGHTS];
osg::StateSet *lightStateSet;
osg::Group * startupScene()
{
	//球
	osg::Geode *sphere = new osg::Geode();
	sphere->addDrawable(new osg::ShapeDrawable(new osg::Sphere(osg::Vec3(-2, 0, 0), 1)));
	//正方体
	osg::Geode *cube = createCube();
	cubeTransform = new osg::PositionAttitudeTransform();
	cubeTransform->addChild(cube);
	cubeTransform->setPosition(osg::Vec3(2, 0, -1));
	//金字塔
	osg::Geode *pyramid = createPyramid();
	pyramidTransform = new osg::PositionAttitudeTransform();
	pyramidTransform->addChild(pyramid);
	pyramidTransform->setPosition(osg::Vec3(5, 0, -1));

	// create white material
	osg::Material *material = new osg::Material();
	material->setDiffuse(osg::Material::FRONT, osg::Vec4(1.0, 1.0, 1.0, 1.0));
	material->setSpecular(osg::Material::FRONT, osg::Vec4(0.0, 0.0, 0.0, 1.0));
	material->setAmbient(osg::Material::FRONT, osg::Vec4(0.1, 0.1, 0.1, 1.0));
	material->setEmission(osg::Material::FRONT, osg::Vec4(0.0, 0.0, 0.0, 1.0));
	material->setShininess(osg::Material::FRONT, 25.0);

	// assign the material to the sphere and cube
	sphere->getOrCreateStateSet()->setAttribute(material);
	cube->getOrCreateStateSet()->setAttribute(material);

	// Create Lights - Red, Green, Blue
	osg::Vec4 lightColors[] = { osg::Vec4(1.0, 0.0, 0.0, 1.0), osg::Vec4(0.0, 1.0, 0.0, 1.0), osg::Vec4(0.0, 0.0, 1.0, 1.0) };

	osg::Group *root = new osg::Group();
	lightStateSet = root->getOrCreateStateSet();

	osg::Geode *lightMarker[LIGHTS];
	osg::LightSource *lightSource[LIGHTS];

	for (int i = 0; i < LIGHTS; i++) {
		lightMarker[i] = new osg::Geode();
		lightMarker[i]->addDrawable(new osg::ShapeDrawable(new osg::Sphere(osg::Vec3(), 1)));
		lightMarker[i]->getOrCreateStateSet()->setAttribute(createSimpleMaterial(lightColors[i]));

		lightSource[i] = new osg::LightSource();
		lightSource[i]->setLight(createLight(lightColors[i]));
		lightSource[i]->setLocalStateSetModes(osg::StateAttribute::ON);
		lightSource[i]->setStateSetModes(*lightStateSet, osg::StateAttribute::ON);

		lightTransform[i] = new osg::PositionAttitudeTransform();
		lightTransform[i]->addChild(lightSource[i]);
		lightTransform[i]->addChild(lightMarker[i]);
		lightTransform[i]->setPosition(osg::Vec3(0, 0, 5));
		lightTransform[i]->setScale(osg::Vec3(0.1, 0.1, 0.1));

		root->addChild(lightTransform[i]);
	}

		root->addChild(sphere);
		root->addChild(cubeTransform);
		root->addChild(pyramidTransform);
		return root;
}

float myTimer = 0;
void update(float dt) {
	myTimer += 0.01*dt;
	lightTransform[0]->setPosition(osg::Vec3(cos(myTimer), sin(myTimer), 0) * 4);
	lightTransform[1]->setPosition(osg::Vec3(0, cos(myTimer), sin(myTimer)) * 4);
	lightTransform[2]->setPosition(osg::Vec3(sin(myTimer), cos(myTimer), sin(myTimer)) * 4);
} 

const bool offScreen = false;
const int width = 640;
const int height = 480; ;
void initCanvas(osg::ref_ptr<osgViewer::Viewer> viewer) {
	int x = 20;
	int y = 20;
	osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;
	traits->x = x;
	traits->y = y;
	traits->width = width;
	traits->height = height;
	if (offScreen) {
		traits->windowDecoration = false;
		traits->doubleBuffer = true;
		traits->pbuffer = true;
	}
	else {
		traits->windowDecoration = true;
		traits->doubleBuffer = true;
		traits->pbuffer = false;
	}
	traits->windowName = "http://blog.csdn.net/boksic";
	traits->sharedContext = 0;
	traits->alpha = 8;
	traits->readDISPLAY();
	traits->setUndefinedScreenDetailsToDefaultScreen();

	osg::GraphicsContext* _gc = osg::GraphicsContext::createGraphicsContext(traits.get());

	if (!_gc) {
		osg::notify(osg::NOTICE)
			<< "Failed to create pbuffer, failing back to normal graphics window." << endl;

		traits->pbuffer = false;
		_gc = osg::GraphicsContext::createGraphicsContext(traits.get());
	}
	viewer->getCamera()->setGraphicsContext(_gc);
	viewer->getCamera()->setViewport(new osg::Viewport(x, y, width, height));
	viewer->getCamera()->setClearColor(osg::Vec4(0, 0, 0, 1));

	viewer->setCameraManipulator(new osgGA::TrackballManipulator);
	viewer->setThreadingModel(osgViewer::ViewerBase::SingleThreaded);
	viewer->realize();
	viewer->setReleaseContextAtEndOfFrameHint(false);
}

int main(int argc, const char* argv[]) {
	osg::Group *scene = startupScene();

	osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer;
	viewer->setSceneData(scene);
	initCanvas(viewer);

	while (!viewer->done()) {
		viewer->frame();
		update(0.5); // do the update advancing 500ms
	}
	return 0;
}
时间: 2024-12-16 10:39:39

OpenSceneGraph基础:光照的相关文章

OpenGL(十一) 可编程管线 基础光照 的实现

在OpenGL中创建 基础光照 ,主要的工作将模型中的法线信息和法线空间运算矩阵传入到shader中.另一方面,LightDir,ViewDir通常是在shader中从引擎参数获取的,为了简化光照模型的实现,这里我们可以在shader中写死.至于经典的 ambient+diffuse+specular 光照原理,不是本文的重点,就在shader中一笔带过了. 原理 通过函数 glm::mat4 normalMatrix = glm::inverseTranspose(s_shaderData.m

颜色,基础光照,材质。

本片blog主要是为了整理脑内一些混杂的知识. 颜色: 大自然中的物体都有着自己独一无二的颜色,我们需要用电脑去模拟这种颜色(尽管是用有限的电脑颜色去模拟无限的自然界存在的颜色,但是你基本看不出来区别). 严格地说,平时生活中我们看到的某一个物体的颜色并不是它本身的颜色,而是它所反射(reflected)出来的颜色:想象一下,你在黑暗中看到自己的手基本是黑乎乎的一片,这就是它在弱光条件下所反射出来的颜色.也就是说,在不同的光源条件下,物体会反射出不同的颜色(也就是物体不吸收的光).这也就是我们需

第五章 Unity中的基础光照(2)

目录 1. Unity中的环境光和自发光 2. 在UnityShader中实现漫反射光照模型 2.1 实践:逐顶点光照 2.2 实践:逐像素光照 2.3 半兰伯特模型 1. Unity中的环境光和自发光 在标准光照模型中,环境光和自发光的计算是最简单的. 在Unity中,场景中的环境光可以在Window->Lighting->Ambient Source/Ambient Intensity中控制,如下图所示.在Shader中,我们只需要通过Unity的内置变量UNITY_LIGHTMODEL_

OpenSceneGraph基础:Helloworld

OpenSceneGraph的基本流程(main函数): 转载请注明http://blog.csdn.net/boksic 如有疑问欢迎留言 int main() { Group *scene = startupScene(); osgViewer::Viewer viewer; viewer.setSceneData(scene); viewer.setCameraManipulator(new osgGA::TrackballManipulator); viewer.realize(); w

Unity Shader入门精要学习笔记 - 第6章 开始 Unity 中的基础光照

转自冯乐乐的<Unity Shader入门精要> 通常来讲,我们要模拟真实的光照环境来生成一张图像,需要考虑3种物理现象. 首先,光线从光源中被发射出来. 然后,光线和场景中的一些物体相交:一些光线被物体吸收了,而另一些光线被散射到其他方向. 最后,摄像机吸收了一些光,产生了一张图像. 在光学中,我们使用辐照度来量化光.对于平行光来说,它的辐照度可通过计算在垂直于l的单位面积上单位时间内穿过的能量来得到.在计算光照模型时,我们需要知道一个物体表面的辐照度,而物体表面往往是和l不垂直的,我们可以

Unity Shader 之 基础光照

摄像机是如何看这个世界的 游戏中摄像机所看到的世界与我们现实中所看到的几乎是一样的. 首先,光线从光源中发射出来. 然后,光线和场景中的一些物体相交(散射,吸收). 最后,摄像机吸收了一些光,产生一张图像. 光线与物体相交的结果有两个:散射(scattering)和吸收(absorption) 散射:只改变光线的方向,但不改变光线的密度和颜色,有两种方向:内部与外部,对应折射与反射. 折射(refraction):散射到物体内部,用漫反射(diffuse)模型来计算. 反射(reflection

基础光照

一.冯氏光照模型 其主要结构由3个分量组成:环境(ambient).漫反射(diffuse).镜面(specular)光照.下边这张图展示了这些分量看起来的样子: 环境光照:即使在黑暗的环境下,世界上通常也仍然有一些光亮(月亮.远处的光),所以物体几乎永远不是完全黑暗的.为了模拟这种效果,我们会使用一个环境光照常量,它永远会给物体一些颜色. 漫反射光照:模拟光源对物体的方向性影响.它是冯氏光照模型中最显著的分量.物体的某一部分越是正对着光源,它就会越亮. 镜面光照:模拟有光泽物体上面出现的亮点.

颜色和基础光照

一: 颜色 我们在现实生活中看到某一物体的颜色并不是这个物体真正拥有的颜色,而是它所反射的(Reflected)颜色. 那些不能被物体所吸收(Absorb)的颜色(被拒绝的颜色)就是我们能够感知到的物体的颜色. 白色的阳光实际上是所有可见颜色的集合,物体吸收了其中的大部分颜色.它仅反射了代表物体颜色的部分,被反射颜色的组合就是我们所感知到的颜色. 当我们在OpenGL中创建一个光源时,我们希望给光源一个颜色.在上一段中我们有一个白色的太阳,所以我们也将光源设置为白色.当我们把光源的颜色与物体的颜

OSG绘制空间凹多边形并计算其面积

目录 1. 思路 1) 多边形分格化 2) 几何图元遍历 2. 实现 3. 参考 1. 思路 这个问题其实涉及到OSG中的两个问题:多边形分格化和几何图元遍历. 1) 多边形分格化 在OpenGL/OSG中,由于效率的原因,默认是直接显示的简单的凸多边形.如果直接强行显示凹多边形,渲染结果是不确定的.所以对于复杂的凹多边形,需要将其分解成简单的凸多边形,这个过程就是多边形分格化.在OSG中是通过osgUtil::Tessellator类来实现多边形分格化的. 2) 几何图元遍历 对于二维的凹多边