OSG 实例化绘制

#include <osgDB/ReadFile>
#include <osgViewer/Viewer>
#include <osg/Geometry>
#include <osg/Texture2D>

#include <osgDB/WriteFile>

#include <iostream>

void
createDAIGeometry(osg::Geometry& geom, int nInstances = 1)
{
	const float halfDimX(.5);
	const float halfDimZ(.5);

	osg::Vec3Array* v = new osg::Vec3Array;
	v->resize(4);
	geom.setVertexArray(v);

	// Geometry for a single quad.
	(*v)[0] = osg::Vec3(-halfDimX, 0., -halfDimZ);
	(*v)[1] = osg::Vec3(halfDimX, 0., -halfDimZ);
	(*v)[2] = osg::Vec3(halfDimX, 0., halfDimZ);
	(*v)[3] = osg::Vec3(-halfDimX, 0., halfDimZ);

	// Use the DrawArraysInstanced PrimitiveSet and tell it to draw 1024 instances.
	geom.addPrimitiveSet(new osg::DrawArrays(GL_QUADS, 0, 4, 1024));
}


osg::StateSet*
createStateSet()
{
	osg::ref_ptr< osg::StateSet > ss = new osg::StateSet;

	// Create a vertex program that references the gl_InstanceID to
	// render each instance uniquely. gl_InstanceID will be in the range
	// 0 to numInstances-1 (1023 in our case).
	std::string vertexSource =
		"#version 330 compatibility\n"  //使用兼容模式的着色器
		"#extension GL_ARB_draw_instanced : enable\n"
		"uniform sampler2D osgLogo; \n"
		"uniform float osg_SimulationTime; \n"

		"void main() \n"
		"{ \n"
		// Using the instance ID, generate "texture coords" for this instance.
		"vec2 tC; \n"
		"float r = float(gl_InstanceID) / 32.; \n"
		"tC.s = fract( r ); tC.t = floor( r ) / 32.; \n"
		// Get the color from the OSG logo.
		"gl_FrontColor = texture2D( osgLogo, tC ); \n"

		// Use the (scaled) tex coord to translate the position of the vertices.
		"vec4 pos = vec4( tC.s * 48., 0., tC.t * 48., 1. ); \n"

		// Compute a rotation angle from the instanceID and elapsed time.
		"float timeOffset = gl_InstanceID / (32. * 32.); \n"
		"float angle = ( osg_SimulationTime - timeOffset ) * 6.283; \n"
		"float sa = sin( angle ); \n"
		"float ca = cos( angle ); \n"
		// New orientation, rotate around z axis.
		"vec4 newX = vec4( ca, sa, 0., 0. ); \n"
		"vec4 newY = vec4( sa, ca, 0., 0. ); \n"
		"vec4 newZ = vec4( 0., 0., 1., 0. ); \n"
		"mat4 mV = mat4( newX, newY, newZ, pos ); \n"
		"gl_Position = ( gl_ModelViewProjectionMatrix * mV * gl_Vertex ); \n"
		"} \n";

	osg::ref_ptr< osg::Shader > vertexShader = new osg::Shader();
	vertexShader->setType(osg::Shader::VERTEX);
	vertexShader->setShaderSource(vertexSource);

	osg::ref_ptr< osg::Program > program = new osg::Program();
	program->addShader(vertexShader.get());

	ss->setAttribute(program.get(),
		osg::StateAttribute::ON | osg::StateAttribute::PROTECTED);

	osg::ref_ptr< osg::Image> iLogo = osgDB::readRefImageFile("Images/osg128.png");
	if (!iLogo.valid())
	{
		osg::notify(osg::ALWAYS) << "Can't open image file osg128.png" << std::endl;
		return(NULL);
	}
	osg::Texture2D* texLogo = new osg::Texture2D(iLogo.get());
	texLogo->setFilter(osg::Texture2D::MIN_FILTER, osg::Texture2D::LINEAR);
	texLogo->setFilter(osg::Texture2D::MAG_FILTER, osg::Texture2D::LINEAR);

	ss->setTextureAttribute(0, texLogo);

	osg::ref_ptr< osg::Uniform > texLogoUniform =
		new osg::Uniform("osgLogo", 0);
	ss->addUniform(texLogoUniform.get());

	return(ss.release());
}


void drawIt()
{

	// Make a scene graph consisting of a single Geode, containing
	 // a single Geometry, and a single PrimitiveSet.
	osg::ref_ptr< osg::Geode > geode = new osg::Geode;

	osg::ref_ptr< osg::Geometry > geom = new osg::Geometry;
	// Configure the Geometry for use with EXT_draw_arrays:
	// DL off and buffer objects on.
	geom->setUseDisplayList(false);
	geom->setUseVertexBufferObjects(true);
	// OSG has no clue where out vertex shader will place the geometric data,
	// so specify an initial bound to allow proper culling and near/far computation.
	osg::BoundingBox bb(-1., -.1, -1., 49., 1., 49.);
	geom->setInitialBound(bb);
	// Add geometric data and the PrimitiveSet. Specify numInstances as 32*32 or 1024.
	createDAIGeometry(*geom, 1);
	geode->addDrawable(geom.get());

	// Create a StateSet to render the instanced Geometry.
	osg::ref_ptr< osg::StateSet > ss = createStateSet();
	geode->setStateSet(ss.get());

	 osgDB::writeNodeFile(*geode, "instanced.osgt");

	osgViewer::Viewer viewer;
	viewer.setSceneData(geode.get());
	viewer.setUpViewInWindow(100, 100, 800, 600);
	viewer.addEventHandler(new osgViewer::StatsHandler);
	viewer.run();
}





int main(int argc, char *argv[])
{
	drawIt();
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值