root/OpenSceneGraph/trunk/src/osgShadow/ShadowMap.cpp @ 6997

Revision 6997, 11.2 kB (checked in by robert, 7 years ago)

Added default values for ambientBias

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
2 *
3 * This library is open source and may be redistributed and/or modified under 
4 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
5 * (at your option) any later version.  The full license is in LICENSE file
6 * included with this distribution, and on the openscenegraph.org website.
7 *
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 * OpenSceneGraph Public License for more details.
12*/
13
14#include <osgShadow/ShadowMap>
15#include <osgShadow/ShadowedScene>
16#include <osg/Notify>
17#include <osg/ComputeBoundsVisitor>
18#include <osg/PolygonOffset>
19#include <osg/CullFace>
20#include <osg/io_utils>
21
22using namespace osgShadow;
23
24
25//////////////////////////////////////////////////////////////////
26// fragment shader
27//
28static const char fragmentShaderSource_noBaseTexture[] =
29    "uniform sampler2DShadow shadowTexture; \n"
30    "uniform vec2 ambientBias; \n"
31    "\n"
32    "void main(void) \n"
33    "{ \n"
34    "    gl_FragColor = gl_Color * (ambientBias.x + shadow2DProj( shadowTexture, gl_TexCoord[0] ) * ambientBias.y); \n"
35    "}\n";
36
37//////////////////////////////////////////////////////////////////
38// fragment shader
39//
40static const char fragmentShaderSource_withBaseTexture[] =
41    "uniform sampler2D baseTexture; \n"
42    "uniform sampler2DShadow shadowTexture; \n"
43    "uniform vec2 ambientBias; \n"
44    "\n"
45    "void main(void) \n"
46    "{ \n"
47    "    vec4 color = gl_Color * texture2D( baseTexture, gl_TexCoord[0].xy ); \n"
48    "    gl_FragColor = color * (ambientBias.x + shadow2DProj( shadowTexture, gl_TexCoord[1] ) * ambientBias.y); \n"
49    "}\n";
50
51ShadowMap::ShadowMap():
52    _textureUnit(1),
53    _ambientBias(0.3f,1.2f)
54{
55}
56
57ShadowMap::ShadowMap(const ShadowMap& copy, const osg::CopyOp& copyop):
58    ShadowTechnique(copy,copyop),
59    _textureUnit(copy._textureUnit),
60    _ambientBias(copy._ambientBias)
61{
62}
63
64void ShadowMap::setTextureUnit(unsigned int unit)
65{
66    _textureUnit = unit;
67}
68
69void ShadowMap::setAmbientBias(const osg::Vec2& ambientBias)
70{
71    _ambientBias = ambientBias;
72}
73
74void ShadowMap::init()
75{
76    if (!_shadowedScene) return;
77
78    unsigned int tex_width = 1024;
79    unsigned int tex_height = 1024;
80   
81    _texture = new osg::Texture2D;
82    _texture->setTextureSize(tex_width, tex_height);
83    _texture->setInternalFormat(GL_DEPTH_COMPONENT);
84    _texture->setShadowComparison(true);
85    _texture->setShadowTextureMode(osg::Texture2D::LUMINANCE);
86    _texture->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR);
87    _texture->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR);
88
89    // set up the render to texture camera.
90    {
91        // create the camera
92        _camera = new osg::Camera;
93
94        _camera->setCullCallback(new CameraCullCallback(this));
95
96        _camera->setClearMask(GL_DEPTH_BUFFER_BIT);
97        //_camera->setClearMask(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
98        _camera->setClearColor(osg::Vec4(1.0f,1.0f,1.0f,1.0f));
99        _camera->setComputeNearFarMode(osg::Camera::DO_NOT_COMPUTE_NEAR_FAR);
100
101        // set viewport
102        _camera->setViewport(0,0,tex_width,tex_height);
103
104        // set the camera to render before the main camera.
105        _camera->setRenderOrder(osg::Camera::PRE_RENDER);
106
107        // tell the camera to use OpenGL frame buffer object where supported.
108        _camera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT);
109        //_camera->setRenderTargetImplementation(osg::Camera::SEPERATE_WINDOW);
110
111        // attach the texture and use it as the color buffer.
112        _camera->attach(osg::Camera::DEPTH_BUFFER, _texture.get());
113
114        osg::StateSet* stateset = _camera->getOrCreateStateSet();
115
116        float factor = 0.0f;
117        float units = 1.0f;
118
119        osg::ref_ptr<osg::PolygonOffset> polygon_offset = new osg::PolygonOffset;
120        polygon_offset->setFactor(factor);
121        polygon_offset->setUnits(units);
122        stateset->setAttribute(polygon_offset.get(), osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
123        stateset->setMode(GL_POLYGON_OFFSET_FILL, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
124
125        osg::ref_ptr<osg::CullFace> cull_face = new osg::CullFace;
126        cull_face->setMode(osg::CullFace::FRONT);
127        stateset->setAttribute(cull_face.get(), osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
128        stateset->setMode(GL_CULL_FACE, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
129       
130    }
131   
132    {
133        _stateset = new osg::StateSet;       
134        _stateset->setTextureAttributeAndModes(_textureUnit,_texture.get(),osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
135        _stateset->setTextureMode(_textureUnit,GL_TEXTURE_GEN_S,osg::StateAttribute::ON);
136        _stateset->setTextureMode(_textureUnit,GL_TEXTURE_GEN_T,osg::StateAttribute::ON);
137        _stateset->setTextureMode(_textureUnit,GL_TEXTURE_GEN_R,osg::StateAttribute::ON);
138        _stateset->setTextureMode(_textureUnit,GL_TEXTURE_GEN_Q,osg::StateAttribute::ON);
139       
140        _texgen = new osg::TexGen;
141
142#if 1
143        osg::Program* program = new osg::Program;
144        _stateset->setAttribute(program);
145
146        if (_textureUnit==0)
147        {
148            osg::Shader* fragment_shader = new osg::Shader(osg::Shader::FRAGMENT, fragmentShaderSource_noBaseTexture);
149            program->addShader(fragment_shader);
150
151            osg::Uniform* shadowTextureSampler = new osg::Uniform("shadowTexture",(int)_textureUnit);
152            _stateset->addUniform(shadowTextureSampler);
153        }
154        else
155        {
156            osg::Shader* fragment_shader = new osg::Shader(osg::Shader::FRAGMENT, fragmentShaderSource_withBaseTexture);
157            program->addShader(fragment_shader);
158
159            osg::Uniform* baseTextureSampler = new osg::Uniform("baseTexture",0);
160            _stateset->addUniform(baseTextureSampler);
161
162            osg::Uniform* shadowTextureSampler = new osg::Uniform("shadowTexture",(int)_textureUnit);
163            _stateset->addUniform(shadowTextureSampler);
164        }
165       
166        osg::Uniform* ambientBias = new osg::Uniform("ambientBias",_ambientBias);
167        _stateset->addUniform(ambientBias);
168
169#endif
170    }
171   
172    _dirty = false;
173}
174
175
176void ShadowMap::update(osg::NodeVisitor& nv)
177{
178    _shadowedScene->osg::Group::traverse(nv);
179}
180
181void ShadowMap::cull(osgUtil::CullVisitor& cv)
182{
183    // record the traversal mask on entry so we can reapply it later.
184    unsigned int traversalMask = cv.getTraversalMask();
185
186    osgUtil::RenderStage* orig_rs = cv.getRenderStage();
187
188    // do traversal of shadow recieving scene which does need to be decorated by the shadow map
189    {
190        cv.pushStateSet(_stateset.get());
191   
192        _shadowedScene->osg::Group::traverse(cv);
193       
194        cv.popStateSet();
195
196    }
197   
198    // need to compute view frustum for RTT camera.
199    // 1) get the light position
200    // 2) get the center and extents of the view frustum
201
202    const osg::Light* selectLight = 0;
203    osg::Vec4 lightpos;
204
205    osgUtil::PositionalStateContainer::AttrMatrixList& aml = orig_rs->getPositionalStateContainer()->getAttrMatrixList();
206    for(osgUtil::PositionalStateContainer::AttrMatrixList::iterator itr = aml.begin();
207        itr != aml.end();
208        ++itr)
209    {
210        const osg::Light* light = dynamic_cast<const osg::Light*>(itr->first.get());
211        if (light)
212        {
213            osg::RefMatrix* matrix = itr->second.get();
214            if (matrix) lightpos = light->getPosition() * (*matrix);
215            else lightpos = light->getPosition();
216
217            selectLight = light;
218        }
219    }
220   
221    osg::Matrix eyeToWorld;
222    eyeToWorld.invert(*cv.getModelViewMatrix());
223   
224    lightpos = lightpos * eyeToWorld;
225
226    if (selectLight)
227    {
228
229        // get the bounds of the model.   
230        osg::ComputeBoundsVisitor cbbv(osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN);
231        cbbv.setTraversalMask(getShadowedScene()->getCastsShadowTraversalMask());
232       
233        _shadowedScene->osg::Group::traverse(cbbv);
234       
235        osg::BoundingBox bb = cbbv.getBoundingBox();
236       
237        if (lightpos[3]!=0.0)
238        {
239            osg::Vec3 position(lightpos.x(), lightpos.y(), lightpos.z());
240
241            float centerDistance = (position-bb.center()).length();
242
243            float znear = centerDistance-bb.radius();
244            float zfar  = centerDistance+bb.radius();
245            float zNearRatio = 0.001f;
246            if (znear<zfar*zNearRatio) znear = zfar*zNearRatio;
247
248            float top   = (bb.radius()/centerDistance)*znear;
249            float right = top;
250
251            _camera->setReferenceFrame(osg::Camera::ABSOLUTE_RF);
252            _camera->setProjectionMatrixAsFrustum(-right,right,-top,top,znear,zfar);
253            _camera->setViewMatrixAsLookAt(position,bb.center(),osg::Vec3(0.0f,1.0f,0.0f));
254           
255
256            // compute the matrix which takes a vertex from local coords into tex coords
257            // will use this later to specify osg::TexGen..
258            osg::Matrix MVPT = _camera->getViewMatrix() *
259                               _camera->getProjectionMatrix() *
260                               osg::Matrix::translate(1.0,1.0,1.0) *
261                               osg::Matrix::scale(0.5f,0.5f,0.5f);
262                               
263            _texgen->setMode(osg::TexGen::EYE_LINEAR);
264            _texgen->setPlanesFromMatrix(MVPT);
265        }
266        else
267        {
268            // make an orthographic projection
269            osg::Vec3 lightDir(lightpos.x(), lightpos.y(), lightpos.z());
270            lightDir.normalize();
271
272            // set the position far away along the light direction
273            osg::Vec3 position = lightDir * bb.radius()  * 20;
274
275            float centerDistance = (position-bb.center()).length();
276
277            float znear = centerDistance-bb.radius();
278            float zfar  = centerDistance+bb.radius();
279            float zNearRatio = 0.001f;
280            if (znear<zfar*zNearRatio) znear = zfar*zNearRatio;
281
282            float top   = bb.radius();
283            float right = top;
284
285            _camera->setReferenceFrame(osg::Camera::ABSOLUTE_RF);
286            _camera->setProjectionMatrixAsOrtho(-right, right, -top, top, znear, zfar);
287            _camera->setViewMatrixAsLookAt(position,bb.center(),osg::Vec3(0.0f,1.0f,0.0f));
288           
289
290            // compute the matrix which takes a vertex from local coords into tex coords
291            // will use this later to specify osg::TexGen..
292            osg::Matrix MVPT = _camera->getViewMatrix() *
293                               _camera->getProjectionMatrix() *
294                               osg::Matrix::translate(1.0,1.0,1.0) *
295                               osg::Matrix::scale(0.5f,0.5f,0.5f);
296                               
297            _texgen->setMode(osg::TexGen::EYE_LINEAR);
298            _texgen->setPlanesFromMatrix(MVPT);
299        }
300
301
302        cv.setTraversalMask( traversalMask &
303                             getShadowedScene()->getCastsShadowTraversalMask() );
304
305        // do RTT camera traversal
306        _camera->accept(cv);
307
308        orig_rs->getPositionalStateContainer()->addPositionedTextureAttribute(_textureUnit, cv.getModelViewMatrix(), _texgen.get());
309    }
310
311
312    // reapply the original traversal mask
313    cv.setTraversalMask( traversalMask );
314}
315
316void ShadowMap::cleanSceneGraph()
317{
318}
Note: See TracBrowser for help on using the browser.