#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;
}
OSG 实例化绘制
最新推荐文章于 2025-05-20 18:02:11 发布