shadowmap示例,根据http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-16-shadow-mapping/教程用osg写的demo
原理在教程上说的很清楚了
/*
*shadowmap示例,根据http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-16-shadow-mapping/教程用osg写的demo
*缪国凯
*MK([email protected])
*/
#include "../Common/Common.h"
#include <osg/AlphaFunc>
#include <osg/Texture2D>
#include <osg/Shape>
#include <osg/ShapeDrawable>
#define AREA 10
#define SM_TEXTURE_WIDTH 4096
void loadShaders( osg::StateSet* ss, std::string filepath = "shader")
{
osg::Shader *fragShader=new osg::Shader(osg::Shader::FRAGMENT);
osg::Shader *vertShader=new osg::Shader(osg::Shader::VERTEX);
if(!fragShader->loadShaderSourceFromFile(filepath+".frag"))
{
printf("加载%s失败\n",(filepath+".frag").c_str());
};
printf("加载%s成功\n", (filepath + ".frag").c_str());
if(!vertShader->loadShaderSourceFromFile(filepath+".vert"))
{
printf("加载%s失败\n", (filepath + ".vert").c_str());
};
printf("加载%s成功\n", (filepath + ".vert").c_str());
osg::ref_ptr<osg::Program> program = new osg::Program;
program->addShader( vertShader);
program->addShader( fragShader);
if ( ss )
ss->setAttributeAndModes( program.get(), osg::StateAttribute::ON );
}
osg::Node* CreateModel(osg::Texture2D* tex, osg::Image *img, int width = 4.0, osg::Vec4 tmpColor = osg::Vec4(1.0, 1.0, 1.0, 1.0))
{
osg::Geometry *_geo = new osg::Geometry;
osg::Vec3Array * pCoords = new osg::Vec3Array;
osg::Vec3Array * pNormals = new osg::Vec3Array;
pNormals->push_back(osg::Vec3(0.0f, 0.0f, 1.0f));
osg::Vec4Array * pColors = new osg::Vec4Array;
pColors->push_back(tmpColor);
_geo->setNormalArray(pNormals);
_geo->setNormalBinding(osg::Geometry::BIND_OVERALL);
_geo->setColorArray(pColors);
_geo->setColorBinding(osg::Geometry::BIND_OVERALL);
osg::ref_ptr<osg::Vec2Array> _coords = new osg::Vec2Array;
_geo->setTexCoordArray(0, _coords);
pCoords->push_back(osg::Vec3(-width/2, width/2, 0.0));
_coords->push_back(osg::Vec2(0.0, 0.0));
pCoords->push_back(osg::Vec3(width/2, width/2, 0.0));
_coords->push_back(osg::Vec2(1.0, 0.0));
pCoords->push_back(osg::Vec3(width/2, -width/2, 0.0));
_coords->push_back(osg::Vec2(1.0, 1.0));
pCoords->push_back(osg::Vec3(-width/2, -width/2, 0.0));
_coords->push_back(osg::Vec2(0.0, 1.0));
_geo->setVertexArray(pCoords);
_geo->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS, 0, pCoords->size()));
osg::Geode *_geo_LocalPlane = new osg::Geode;
_geo_LocalPlane->addDrawable(_geo);
{
osg::StateSet* stateset = _geo_LocalPlane->getOrCreateStateSet();
stateset->setMode(GL_BLEND, osg::StateAttribute::ON);
stateset->setMode(GL_LIGHTING, osg::StateAttribute::OFF | osg::StateAttribute::PROTECTED);
osg::ref_ptr<osg::BlendFunc> blendFunc = new osg::BlendFunc();
blendFunc->setSource(osg::BlendFunc::SRC_ALPHA);
blendFunc->setDestination(osg::BlendFunc::ONE_MINUS_SRC_ALPHA);
osg::AlphaFunc* alphaFunc = new osg::AlphaFunc;
alphaFunc->setFunction(osg::AlphaFunc::GEQUAL, 0.5f);
stateset->setAttributeAndModes(alphaFunc, osg::StateAttribute::ON);
if (NULL != tex && img == NULL)
{
stateset->setTextureAttributeAndModes(0, tex, osg::StateAttribute::ON);
}
else if (NULL != img)
{
osg::ref_ptr<osg::Texture2D> texture = new osg::Texture2D;
texture->setImage(img);
texture->setFilter(osg::Texture2D::MIN_FILTER, osg::Texture2D::NEAREST);
texture->setFilter(osg::Texture2D::MAG_FILTER, osg::Texture2D::NEAREST);
texture->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE);
texture->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE);
stateset->setTextureAttributeAndModes(0, texture, osg::StateAttribute::ON);
}
}
return _geo_LocalPlane;
}
osg::Texture2D* CreateDepthTexture(int width, int height)
{
osg::Texture2D* _texture = new osg::Texture2D;
_texture->setTextureSize(width, height);
_texture->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE);
_texture->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE);
_texture->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR);
_texture->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR);
_texture->setInternalFormat(GL_DEPTH_COMPONENT);
_texture->setSourceFormat(GL_DEPTH_COMPONENT);
_texture->setSourceType(GL_FLOAT);
//tex->setShadowComparison(true);
_texture->setShadowTextureMode(osg::Texture2D::LUMINANCE);
return _texture;
}
osg::Image* CreateDepthImg(int width, int height)
{
osg::Image *depthImg = new osg::Image;
depthImg->allocateImage(width, height, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_FLOAT);
return depthImg;
}
osg::Camera* CreateShadowMapCamera(int x, int y, int w, int h, osg::Texture2D *_texture2D)
{
osg::ref_ptr<osg::Camera> _camera = new osg::Camera;
_camera->setReferenceFrame(osg::Camera::ABSOLUTE_RF);
_camera->setClearMask(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
_camera->setClearColor(osg::Vec4(1.0f,1.0f,1.0f,1.0f));
_camera->setComputeNearFarMode(osg::Camera::DO_NOT_COMPUTE_NEAR_FAR);
_camera->setViewport(0,0,w, h);
_camera->setRenderOrder(osg::Camera::PRE_RENDER);
_camera->setProjectionMatrixAsOrtho(-AREA, AREA, -AREA, AREA, -AREA, 3*AREA);
osg::Vec3 tmpEyeps(0, 9, 15);
_camera->setViewMatrixAsLookAt(tmpEyeps, osg::Vec3(0, 0, 0), osg::Vec3(0, 1, 0));
_camera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT);
_camera->attach(osg::Camera::DEPTH_BUFFER, _texture2D);
return _camera.release();
}
osg::Camera* initCamera(int x, int y, int w, int h)
{
osg::Camera * _camera = new osg::Camera;
_camera = new osg::Camera;
_camera->setName("CCTV");
_camera->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
_camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
_camera->setNearFarRatio(0.000001);
//_camera->setClearColor(osg::Vec4f(0.0,0.0,0.0,0.25));
_camera->setProjectionMatrixAsPerspective(30.0, (float)w/(float)h, 1,10000.0);
_camera->setViewport(x, y, w, h);
_camera->setComputeNearFarMode(osg::Camera::DO_NOT_COMPUTE_NEAR_FAR);
return _camera;
}
osg::ref_ptr<osg::Camera> createTestHUD(int x, int y, int w, int h, osg::Texture2D *tex)
{
osg::ref_ptr<osg::Camera> hudCamera = new osg::Camera;
hudCamera->setProjectionMatrixAsOrtho2D(0, 1, 0, 1);
hudCamera->setViewMatrix(osg::Matrix::identity());
hudCamera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
hudCamera->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
hudCamera->setClearColor(osg::Vec4(1.0, 1.0, 1.0, 1.0));
hudCamera->setRenderOrder(osg::Camera::POST_RENDER);
hudCamera->setAllowEventFocus(false);
hudCamera->setViewport(x, y, w, h);
hudCamera->setComputeNearFarMode(osg::Camera::DO_NOT_COMPUTE_NEAR_FAR);
osg::ref_ptr<osg::Geode> geode = new osg::Geode;
osg::ref_ptr<osg::Geometry> geom = new osg::Geometry;
osg::ref_ptr<osg::Vec3Array> vc = new osg::Vec3Array;
vc->push_back(osg::Vec3d(0, 0, 0));
vc->push_back(osg::Vec3d(1, 0, 0));
vc->push_back(osg::Vec3d(1, 1, 0));
vc->push_back(osg::Vec3d(0, 1, 0));
geom->setVertexArray(vc.get());
osg::ref_ptr<osg::Vec2Array> vt = new osg::Vec2Array;
vt->push_back(osg::Vec2(0, 0));
vt->push_back(osg::Vec2(1, 0));
vt->push_back(osg::Vec2(1, 1));
vt->push_back(osg::Vec2(0, 1));
geom->setTexCoordArray(0, vt.get());
geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS, 0, 4));
geode->addDrawable(geom.get());
hudCamera->addChild(geode.get());
osg::StateSet *stateset = geode->getOrCreateStateSet();
if (NULL != tex)
{
stateset->setTextureAttributeAndModes(0, tex, osg::StateAttribute::ON);
}
return hudCamera;
}
void main()
{
osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer;
osg::ref_ptr<osg::Group> root = new osg::Group;
osg::Group * tmpGroup = new osg::Group;
osg::Node *roomNode = osgDB::readNodeFile("room.ive");
roomNode->getOrCreateStateSet()->setTextureAttributeAndModes(0,new osg::Texture2D(osgDB::readImageFile("meinv.bmp")));
viewer->getCamera()->getOrCreateStateSet()->setMode(GL_LIGHTING,osg::StateAttribute::OFF | osg::StateAttribute::OVERRIDE);
osg::ref_ptr<osg::Texture2D> tmpTexture = CreateDepthTexture(SM_TEXTURE_WIDTH, SM_TEXTURE_WIDTH);
osg::ref_ptr<osg::Camera> shadowMapCamera = CreateShadowMapCamera(0, 0, SM_TEXTURE_WIDTH, SM_TEXTURE_WIDTH, tmpTexture.get());
root->addChild(shadowMapCamera.get());
shadowMapCamera->addChild(tmpGroup);
osg::ref_ptr<osg::Camera> tmpCamera = initCamera(1000, 0, 400, 400);
root->addChild(tmpCamera.get());
tmpCamera->addChild(tmpGroup);
osg::ref_ptr<osg::ShapeDrawable> shape = new osg::ShapeDrawable(new osg::Box(osg::Vec3(3, 0, 3), 2, 2, 6));
osg::ref_ptr<osg::ShapeDrawable> shape1 = new osg::ShapeDrawable(new osg::Sphere(osg::Vec3(0, 0, 0), 2));
osg::ref_ptr<osg::ShapeDrawable> shape2 = new osg::ShapeDrawable(new osg::Box(osg::Vec3(-3, 0, 3), 2, 2, 6));
osg::ref_ptr<osg::Geode> geode = new osg::Geode;
geode->addDrawable(shape);
geode->addDrawable(shape1);
geode->addDrawable(shape2);
tmpGroup->addChild(roomNode);
root->addChild(tmpGroup);
osg::ref_ptr<osg::ShapeDrawable> shapeSun = new osg::ShapeDrawable(new osg::Sphere(osg::Vec3(0, 0, 2), 0.3));
osg::ref_ptr<osg::Geode> geodeSun = new osg::Geode;
osg::ref_ptr<osg::MatrixTransform> transformSun = new osg::MatrixTransform;
geodeSun->addDrawable(shapeSun.get());
transformSun->addChild(geodeSun.get());
root->addChild(transformSun);
osg::ref_ptr<osg::Camera> tmpShowShadowMapCamera = createTestHUD(1000, 400, 300, 300, tmpTexture);
root->addChild(tmpShowShadowMapCamera.get());
viewer->setSceneData(root);
viewer->setUpViewInWindow(100, 100, 1400, 768);
viewer->addEventHandler(new osgViewer::StatsHandler);
osgGA::TrackballManipulator *tmpManipulator = new osgGA::TrackballManipulator;
viewer->setCameraManipulator(tmpManipulator);
viewer->getCamera()->setComputeNearFarMode(osg::Camera::DO_NOT_COMPUTE_NEAR_FAR);
osg::StateSet *shaderStateSet = tmpCamera->getOrCreateStateSet();
shaderStateSet->setTextureAttributeAndModes(1,tmpTexture, osg::StateAttribute::ON);
loadShaders(shaderStateSet, "ShadowMapShader");
shaderStateSet->getOrCreateUniform("u_Texture0",osg::Uniform::Type::SAMPLER_2D)->set(0);
shaderStateSet->getOrCreateUniform("shadowMap",osg::Uniform::Type::SAMPLER_2D)->set(1);
float tmpAg = 0.0;
float tmpLen = 15;
int frameIndex = 0;
while(!viewer->done())
{
tmpCamera->setViewMatrix(tmpManipulator->getInverseMatrix());
tmpAg += 0.001;
osg::Vec3 tmpEyeps(0, cos(tmpAg) * tmpLen, sin(tmpAg) * tmpLen);
osg::Vec3 tmpSunPs(0, cos(tmpAg) * (tmpLen + 1), sin(tmpAg) * (tmpLen + 1));
shadowMapCamera->setViewMatrixAsLookAt(tmpEyeps, osg::Vec3(0, 0, 0), osg::Vec3(0, 1, 0));
osg::Matrix depthMVP;
transformSun->setMatrix(osg::Matrix::translate(tmpSunPs));
//updata shader
{
// Compute the MVP matrix from the light's point of view
osg::Matrix modelMatrix = osg::Matrix(osg::Matrix::identity());
osg::Matrix viewMatrix = shadowMapCamera->getViewMatrix();
osg::Matrix projectMatrix = shadowMapCamera->getProjectionMatrix();
osg::Matrix biasMatrix(
0.5, 0.0, 0.0, 0.0,
0.0, 0.5, 0.0, 0.0,
0.0, 0.0, 0.5, 0.0,
0.5, 0.5, 0.5, 1.0
);
osg::Matrix DepthBiasMVP = modelMatrix*viewMatrix*projectMatrix*biasMatrix;
shaderStateSet->getOrCreateUniform("DepthBiasMVP", osg::Uniform::FLOAT_MAT4)->set(DepthBiasMVP);
}
viewer->frame();
}
return;
}
http://download.csdn.net/detail/dancing_night/9677738