osg做阴影时,得不到深度图的问题
各位:用osg::Camera渲染了一个深度图,想把它用到阴影里面,但是,发现整个深度图里面的像素值都是0.可能是代码错误或是Shader错误.这个是模仿一个OpenGL例子来做的,实在找不到问题了.
大家有时间帮我看一下,是哪里有问题,我好改正过来.谢谢了.
代码如下:#include <osg/Group>
#include <osg/MatrixTransform>
#include <osgDB/ReadFile>
#include <osgViewer/Viewer>
#include <osg/Texture>
#include <osg/Texture2D>
#include <osg/Image>
#include <osg/StateSet>
#include <osg/StateAttribute>
#include <osg/Geode>
#include <osg/Array>
#include <osg/Light>
#include <osg/Shape>
#include <osg/ShapeDrawable>
#include <osg/Matrix>
#include <osg/Camera>
#include <osgGA/GUIEventHandler>
#include <osgViewer/View>
#include <osg/Timer>
#include <osg/Program>
#include <osg/Uniform>
#include <osg/Shader>
#include <osg/ColorMask>
class CameraProjectUpdate : public osgGA::GUIEventHandler
{
public:
CameraProjectUpdate( osg::Camera *camera, osg::Light *light, osg::Node *shadowRoot )
{
_shadowCamera = camera;
_light = light;
_shadowRoot = shadowRoot;
_maxtrixUniform = NULL;
}
bool handle( const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa )
{
osgViewer::View *view = dynamic_cast<osgViewer::View*>(&aa);
if ( !view )
{
return false;
}
osg::Camera *camera = view->getCamera();
if ( !camera )
{
return false;
}
osg::BoundingSphere bs = _shadowRoot->getBound();
if (!bs.valid())
{
return false;
}
float znear = 1.0f*bs.radius();
float zfar= 3.0f*bs.radius();
// 2:1 aspect ratio as per flag geometry below.
float proj_top = 0.25f*znear;
float proj_right = 0.5f*znear;
znear *= 0.9f;
zfar *= 1.1f;
_shadowCamera->setProjectionMatrixAsFrustum(-proj_right,proj_right,-proj_top,proj_top,znear,zfar);
osg::Vec4 lightPos = _light->getPosition();
_shadowCamera->setViewMatrixAsLookAt( osg::Vec3( lightPos.x(), lightPos.y(), lightPos.z() ), bs.center(), _light->getDirection() );
// 视图变换矩阵
osg::Matrix lightViewMatrix = _shadowCamera->getViewMatrix();
// 投影矩阵
osg::Matrix lightProjectMatrix = _shadowCamera->getProjectionMatrix();
osg::Matrix cameraInverseViewMatrix = camera->getInverseViewMatrix();
osg::Matrix lightResultMatrix;
if ( ea.getModKeyMask() & osgGA::GUIEventAdapter::MODKEY_SHIFT )
{
lightResultMatrix = cameraInverseViewMatrix * lightViewMatrix * lightProjectMatrix/* * biasMt*/;
}else
{
lightResultMatrix = /*biasMt * */lightProjectMatrix * lightViewMatrix * cameraInverseViewMatrix;
}
if ( !_maxtrixUniform )
{
return false;
}
_maxtrixUniform->set( lightResultMatrix );
return false;
}
osg::Camera *_shadowCamera;
osg::Light *_light;
osg::Node *_shadowRoot;
osg::Uniform *_maxtrixUniform;
};
osg::Texture* createRenderTexture(int tex_width, int tex_height, bool nearest = false)
{
// create simple 2D texture
osg::Texture2D* texture2D = new osg::Texture2D;
texture2D->setTextureSize(tex_width, tex_height);
texture2D->setFilter(osg::Texture2D::MIN_FILTER, nearest ? osg::Texture2D::NEAREST : osg::Texture2D::LINEAR);
texture2D->setFilter(osg::Texture2D::MAG_FILTER, nearest ? osg::Texture2D::NEAREST : osg::Texture2D::LINEAR);
texture2D->setWrap(osg::Texture2D::WRAP_S,osg::Texture2D::CLAMP_TO_EDGE);
texture2D->setWrap(osg::Texture2D::WRAP_T,osg::Texture2D::CLAMP_TO_EDGE);
texture2D->setBorderColor(osg::Vec4(0.0f,0.0f,0.0f,0.0f));
texture2D->setResizeNonPowerOfTwoHint(false);
texture2D->setInternalFormat(GL_RGBA32F_ARB);
texture2D->setSourceFormat(GL_RGBA);
texture2D->setSourceType(GL_FLOAT);
return texture2D;
}
osg::Drawable* createTexturedQuadDrawable(const osg::Vec3& center,const osg::Vec3& widthVec,const osg::Vec3& heightVec, osg::Texture *tex )
{
//osg::Geometry* geom = osg::createTexturedQuadGeometry(corner, widthVec, heightVec, l,b,r,t);
osg::Geometry* geom = new osg::Geometry;
osg::Vec4Array* colors = new osg::Vec4Array;
colors->push_back(osg::Vec4(1.0f,1.0f,1.0f,1.0f));
geom->setColorArray(colors);
geom->setColorBinding(osg::Geometry::BIND_OVERALL);
// Vertex coordinates
osg::Vec3Array* coords = new osg::Vec3Array(4);
(*coords) = center + heightVec / 2 - widthVec / 2;
(*coords) = center - heightVec / 2 - widthVec / 2;
(*coords) = center - heightVec / 2 + widthVec / 2;
(*coords) = center + heightVec / 2 + widthVec / 2;
geom->setVertexArray(coords);
// Add texture coordinates for every input texture
int unit = 0;
// start with default normalised
float l = 0.0;
float b = 0.0;
float r = 1.0;
float t = 1.0;
osg::Vec2Array* tcoords = new osg::Vec2Array(4);
(*tcoords).set(l,t);
(*tcoords).set(l,b);
(*tcoords).set(r,b);
(*tcoords).set(r,t);
geom->setTexCoordArray(unit, tcoords);
osg::Vec3Array* normals = new osg::Vec3Array(1);
(*normals) = widthVec^heightVec;
(*normals).normalize();
geom->setNormalArray(normals);
geom->setNormalBinding(osg::Geometry::BIND_OVERALL);
geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS,0,4));
// setup default state set
geom->setStateSet(new osg::StateSet());
if ( tex )
{
geom->getOrCreateStateSet()->setTextureAttributeAndModes(0, tex );
}
geom->setUseDisplayList(false);
return geom;
}
int _tmain(int argc, _TCHAR* argv[])
{
osgViewer::Viewer v;
osg::ref_ptr<osg::Node> cow = osgDB::readNodeFile("cow.osg");
osg::ref_ptr<osg::Group> root = new osg::Group;
osg::ref_ptr<osg::Group> modelRoot = new osg::Group;
osg::ref_ptr<osg::Group> shadowRoot = new osg::Group;
osg::ref_ptr<osg::Group> modelsGroup = new osg::Group;
modelsGroup->addChild( cessna );
shadowRoot->addChild( modelsGroup );
modelRoot->addChild( modelsGroup );
root->addChild( modelRoot );
// add a sphere to modelsGroup
{
osg::ref_ptr<osg::Geode> shadowGeode = new osg::Geode;
osg::ref_ptr<osg::Sphere> shadowSphere = new osg::Sphere;
shadowSphere->setRadius( 5.0 );
shadowSphere->setCenter( osg::Vec3 ( 0.0, 0.0, 0.0 ) );
osg::ref_ptr<osg::ShapeDrawable> shadowShape = new osg::ShapeDrawable;
shadowShape->setColor( osg::Vec4 ( 1.0, 1.0, 0.0, 1.0 ) );
shadowShape->setShape( shadowSphere );
shadowGeode->addDrawable( shadowShape );
modelsGroup->addChild( shadowGeode );
}
osg::ref_ptr<osg::Light> light = new osg::Light;
osg::Vec3 lightPos = osg::Vec3 ( 0, 0, 100 );
osg::Vec3 lightDir = osg::Vec3 ( 0.0, 0.0, -1.0 );
light->setPosition( osg::Vec4 ( lightPos.x(), lightPos.y(), lightPos.z(), 1.0 ) );
light->setDirection( lightDir );
int windowWidth = 2048;
int windowHeight = 2048;
osg::Texture* textureDepthView = createRenderTexture(windowWidth, windowHeight, true);
// 添加一个平面,表示地面
{
osg::Geode *geode = new osg::Geode;
modelsGroup->addChild( geode );
osg::ref_ptr<osg::Drawable> depthNode = createTexturedQuadDrawable( osg::Vec3 ( 0.0, 0.0, -10.0 )
, osg::Vec3 ( 60.0, 0.0, 0.0 )
, osg::Vec3( 0.0, 60.0, 0.0 )
, NULL );
geode->addDrawable( depthNode );
}
osg::Camera::RenderTargetImplementation renderImplementation = osg::Camera::PIXEL_BUFFER_RTT;/*osg::Camera::FRAME_BUFFER_OBJECT*/;
osg::ref_ptr<osg::Camera> shadowCamera = new osg::Camera;
root->addChild( shadowCamera );
// 在这里,需要设置相机的变换矩阵,从模型到光源空间的变换
// 通过回调这种方式,得到相机的变换矩阵,并设置到uniform里面
CameraProjectUpdate *cpu = new CameraProjectUpdate( shadowCamera, light, shadowRoot );
{
shadowCamera->setEventCallback( cpu );
shadowCamera->setViewport(new osg::Viewport(0,0,windowWidth,windowHeight));
shadowCamera->setClearColor( osg::Vec4 ( 0.0, 0.0, 0.0, 0.0 ) );
textureDepthView->setShadowComparison( true );
textureDepthView->setShadowCompareFunc( osg::Texture::LEQUAL );
shadowCamera->setClearDepth( 1.0 );
shadowCamera->attach(osg::Camera::DEPTH_BUFFER, textureDepthView);
shadowCamera->setRenderTargetImplementation(renderImplementation);
// set view
shadowCamera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
// set the camera to render before the main camera.
shadowCamera->setRenderOrder(osg::Camera::PRE_RENDER);
shadowCamera->addChild( shadowRoot );
}
// setup shadow shader to modelRoot
{
osg::Shader *vertShader = osgDB::readShaderFile( osg::Shader::VERTEX, "ShadowMappingPCF.vert");
osg::Shader *fragShader = osgDB::readShaderFile( osg::Shader::FRAGMENT, "ShadowMappingPCF.frag" );
if ( vertShader && fragShader )
{
osg::Program *progam = new osg::Program;
progam->addShader( vertShader );
progam->addShader( fragShader );
modelRoot->getOrCreateStateSet()->setAttributeAndModes( progam );
modelRoot->getOrCreateStateSet()->setTextureAttributeAndModes( 2, textureDepthView );
modelRoot->getOrCreateStateSet()->addUniform( new osg::Uniform( "shadowMap", 2 ) );
osg::Matrix m;
osg::Uniform *viewMatrixUniform = new osg::Uniform("changeMatrix", m);
modelRoot->getOrCreateStateSet()->addUniform( viewMatrixUniform );
cpu->_maxtrixUniform = viewMatrixUniform;
}
}
// 添加一个小球,表示灯光所有位置
osg::ref_ptr<osg::Geode> geode = new osg::Geode;
root->addChild( geode );
osg::ref_ptr<osg::Sphere> sphere = new osg::Sphere;
sphere->setCenter( lightPos );
sphere->setRadius( 2.0 );
osg::ref_ptr<osg::ShapeDrawable> sd = new osg::ShapeDrawable;
sd->setShape( sphere );
sd->setColor( osg::Vec4 ( 1.0, 1.0, 1.0, 1.0 ) );
geode->addDrawable( sd );
v.setLight( light );
v.setSceneData( root );
return v.run();
return 0;
}
其中用到了两个Shader,如下:
ShadowMappingPCF.vertuniform mat4 changeMatrix;
varying vec4 projCoord;
void main()
{
vec4 texcoord = changeMatrix * gl_ModelViewMatrix * gl_Vertex;
texcoord = texcoord / texcoord.w;
projCoord = 0.5 * projCoord + 0.5;
gl_FrontColor = gl_Color;
gl_Position = ftransform();
}ShadowMappingPCF.fraguniform sampler2DShadow shadowMap;
varying vec4 projCoord;
void main ()
{
vec4 color = gl_Color;
vec3 shadowUV = projCoord.xyz / projCoord.q;
float mapScale = 1.0 / 512.0;
vec4 shadowColor = shadow2D(shadowMap, shadowUV);
shadowColor = clamp(shadowColor, 0.0, 1.0);
if(shadowUV.x >= 0.0 && shadowUV.y >= 0.0
&& shadowUV.x <= 1.0 && shadowUV.y <= 1.0 )
{
gl_FragColor = color * shadowColor;
}
else
{
gl_FragColor = color;
}
} Shader里面有一个错误,修改如下
ShadowMappingPCF.vertuniform mat4 changeMatrix;
varying vec4 projCoord;
void main()
{
vec4 texcoord = changeMatrix * gl_ModelViewMatrix * gl_Vertex;
texcoord = texcoord / texcoord.w;
projCoord = 0.5 * texcoord + 0.5;
gl_FrontColor = gl_Color;
gl_Position = ftransform();
}此时,还是不出阴影 楼主怎么保存深度图像的? ding
保存深度纹理应该是setInternalFormat(GL_DEPTH_COMPONENT);吧
页:
[1]