root/OpenSceneGraph/trunk/examples/osgshadowtexture/CreateShadowedScene.cpp @ 6941

Revision 6941, 8.6 kB (checked in by robert, 7 years ago)

From Martin Lavery and Robert Osfield, Updated examples to use a variation of the MIT License

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/* OpenSceneGraph example, osgshadowtexture.
2*
3*  Permission is hereby granted, free of charge, to any person obtaining a copy
4*  of this software and associated documentation files (the "Software"), to deal
5*  in the Software without restriction, including without limitation the rights
6*  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7*  copies of the Software, and to permit persons to whom the Software is
8*  furnished to do so, subject to the following conditions:
9*
10*  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
11*  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
12*  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
13*  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
14*  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
15*  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
16*  THE SOFTWARE.
17*/
18
19#include <osg/Texture2D>
20#include <osg/Material>
21#include <osg/LightSource>
22#include <osg/Geode>
23#include <osg/Geometry>
24#include <osg/ShapeDrawable>
25#include <osg/Camera>
26#include <osg/TexGenNode>
27#include <osg/Notify>
28#include <osg/io_utils>
29
30#include "CreateShadowedScene.h"
31
32using namespace osg;
33
34class UpdateCameraAndTexGenCallback : public osg::NodeCallback
35{
36    public:
37   
38        UpdateCameraAndTexGenCallback(const osg::Vec3& position, osg::Camera* Camera, osg::TexGenNode* texgenNode):
39            _position(position),
40            _Camera(Camera),
41            _texgenNode(texgenNode)
42        {
43        }
44       
45        virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
46        {
47            // first update subgraph to make sure objects are all moved into postion
48            traverse(node,nv);
49           
50            // now compute the camera's view and projection matrix to point at the shadower (the camera's children)
51            osg::BoundingSphere bs;
52            for(unsigned int i=0; i<_Camera->getNumChildren(); ++i)
53            {
54                bs.expandBy(_Camera->getChild(i)->getBound());
55            }
56           
57            if (!bs.valid())
58            {
59                osg::notify(osg::WARN) << "bb invalid"<<_Camera.get()<<std::endl;
60                return;
61            }
62
63            float centerDistance = (_position-bs.center()).length();
64
65            float znear = centerDistance-bs.radius();
66            float zfar  = centerDistance+bs.radius();
67            float zNearRatio = 0.001f;
68            if (znear<zfar*zNearRatio) znear = zfar*zNearRatio;
69
70            float top   = (bs.radius()/centerDistance)*znear;
71            float right = top;
72
73            _Camera->setReferenceFrame(osg::Camera::ABSOLUTE_RF);
74            _Camera->setProjectionMatrixAsFrustum(-right,right,-top,top,znear,zfar);
75            _Camera->setViewMatrixAsLookAt(_position,bs.center(),osg::Vec3(0.0f,1.0f,0.0f));
76
77            // compute the matrix which takes a vertex from local coords into tex coords
78            // will use this later to specify osg::TexGen..
79            osg::Matrix MVPT = _Camera->getViewMatrix() *
80                               _Camera->getProjectionMatrix() *
81                               osg::Matrix::translate(1.0,1.0,1.0) *
82                               osg::Matrix::scale(0.5f,0.5f,0.5f);
83                               
84            _texgenNode->getTexGen()->setMode(osg::TexGen::EYE_LINEAR);
85            _texgenNode->getTexGen()->setPlanesFromMatrix(MVPT);
86
87        }
88       
89    protected:
90   
91        virtual ~UpdateCameraAndTexGenCallback() {}
92       
93        osg::Vec3                     _position;
94        osg::ref_ptr<osg::Camera> _Camera;
95        osg::ref_ptr<osg::TexGenNode> _texgenNode;
96
97};
98
99
100osg::Group* createShadowedScene(osg::Node* shadower,osg::Node* shadowed,const osg::Vec3& lightPosition,float radius,unsigned int unit)
101{
102    osg::Group* group = new osg::Group;
103   
104    // add light source
105    {
106        osg::LightSource* lightSource = new osg::LightSource;
107        lightSource->getLight()->setPosition(osg::Vec4(lightPosition,1.0f));
108        lightSource->getLight()->setLightNum(0);
109
110        group->addChild(lightSource);
111
112        osg::Geode* lightgeode = new osg::Geode;
113        lightgeode->getOrCreateStateSet()->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
114        lightgeode->addDrawable(new osg::ShapeDrawable(new osg::Sphere(lightPosition,radius)));
115        group->addChild(lightgeode);
116    }
117       
118    osg::Vec4 ambientLightColor(0.2,0.2f,0.2f,1.0f);
119
120    // add the shadower and shadowed.
121    group->addChild(shadower);
122    group->addChild(shadowed);
123
124       
125    unsigned int tex_width = 512;
126    unsigned int tex_height = 512;
127   
128    osg::Texture2D* texture = new osg::Texture2D;
129    texture->setTextureSize(tex_width, tex_height);
130    texture->setInternalFormat(GL_RGB);
131    texture->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR);
132    texture->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR);
133    texture->setWrap(osg::Texture2D::WRAP_S,osg::Texture2D::CLAMP_TO_BORDER);
134    texture->setWrap(osg::Texture2D::WRAP_T,osg::Texture2D::CLAMP_TO_BORDER);
135    texture->setBorderColor(osg::Vec4(1.0f,1.0f,1.0f,1.0f));
136   
137    // set up the render to texture camera.
138    {
139
140        // create the camera
141        osg::Camera* camera = new osg::Camera;
142
143        camera->setClearColor(osg::Vec4(1.0f,1.0f,1.0f,1.0f));
144
145        // set viewport
146        camera->setViewport(0,0,tex_width,tex_height);
147
148        // set the camera to render before the main camera.
149        camera->setRenderOrder(osg::Camera::PRE_RENDER);
150
151        // tell the camera to use OpenGL frame buffer object where supported.
152        camera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT);
153
154        // attach the texture and use it as the color buffer.
155        camera->attach(osg::Camera::COLOR_BUFFER, texture);
156
157        // add subgraph to render
158        camera->addChild(shadower);
159       
160        osg::StateSet* stateset = camera->getOrCreateStateSet();
161
162        // make the material black for a shadow.
163        osg::Material* material = new osg::Material;
164        material->setAmbient(osg::Material::FRONT_AND_BACK,osg::Vec4(0.0f,0.0f,0.0f,1.0f));
165        material->setDiffuse(osg::Material::FRONT_AND_BACK,osg::Vec4(0.0f,0.0f,0.0f,1.0f));
166        material->setEmission(osg::Material::FRONT_AND_BACK,ambientLightColor);
167        material->setShininess(osg::Material::FRONT_AND_BACK,0.0f);
168        stateset->setAttribute(material,osg::StateAttribute::OVERRIDE);
169
170        group->addChild(camera);
171       
172        // create the texgen node to project the tex coords onto the subgraph
173        osg::TexGenNode* texgenNode = new osg::TexGenNode;
174        texgenNode->setTextureUnit(unit);
175        group->addChild(texgenNode);
176
177        // set an update callback to keep moving the camera and tex gen in the right direction.
178        group->setUpdateCallback(new UpdateCameraAndTexGenCallback(lightPosition, camera, texgenNode));
179    }
180
181    // set the shadowed subgraph so that it uses the texture and tex gen settings.   
182    {
183        osg::StateSet* stateset = shadowed->getOrCreateStateSet();
184        stateset->setTextureAttributeAndModes(unit,texture,osg::StateAttribute::ON);
185        stateset->setTextureMode(unit,GL_TEXTURE_GEN_S,osg::StateAttribute::ON);
186        stateset->setTextureMode(unit,GL_TEXTURE_GEN_T,osg::StateAttribute::ON);
187        stateset->setTextureMode(unit,GL_TEXTURE_GEN_R,osg::StateAttribute::ON);
188        stateset->setTextureMode(unit,GL_TEXTURE_GEN_Q,osg::StateAttribute::ON);
189    }
190   
191
192    // set hud to render shadow texture, just for interest
193    {
194        osg::Geode* geode = new osg::Geode;
195        osg::Geometry* geom = osg::createTexturedQuadGeometry(osg::Vec3(0,0,0),osg::Vec3(100.0,0.0,0.0),osg::Vec3(0.0,100.0,0.0));
196        geom->getOrCreateStateSet()->setTextureAttributeAndModes(0,texture,osg::StateAttribute::ON);
197        geom->getOrCreateStateSet()->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
198        geode->addDrawable(geom);
199       
200        osg::Camera* camera = new osg::Camera;
201
202        // set the projection matrix
203        camera->setProjectionMatrix(osg::Matrix::ortho2D(0,100,0,100));
204
205        // set the view matrix   
206        camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
207        camera->setViewMatrix(osg::Matrix::identity());
208       
209        camera->setViewport(50,50,100,100);
210
211        // only clear the depth buffer
212        camera->setClearMask(GL_DEPTH_BUFFER_BIT);
213
214        // draw subgraph after main camera view.
215        camera->setRenderOrder(osg::Camera::POST_RENDER);
216
217        camera->addChild(geode);
218       
219        group->addChild(camera);
220       
221    }
222   
223    return group;
224}
Note: See TracBrowser for help on using the browser.