I am trying to put different lights in a scene and have them cast shadows simultaneously. The problem is that every time I create a new osgShadow::ShadowMap for a light, the previous light stops casting shadow. I suspect that this has something to do with index or something, the same way every light has to have a setLightNum(x) defined. Below is the code used as reference for this image: .
// * Copyright (c) 1982, 1986, 1990, 1991, 1993
// * The Regents of the University of California. All rights reserved.
// *
// * Redistribution and use in source and binary forms, with or without
// * modification, are permitted provided that the following conditions
// * are met:
// * 1. Redistributions of source code must retain the above copyright
// * notice, this list of conditions and the following disclaimer.
// * 2. Redistributions in binary form must reproduce the above copyright
// * notice, this list of conditions and the following disclaimer in the
// * documentation and/or other materials provided with the distribution.
// * 3. All advertising materials mentioning features or use of this software
// * must display the following acknowledgement:
// * This product includes software developed by the University of
// * California, Berkeley and its contributors.
// * 4. Neither the name of the University nor the names of its contributors
// * may be used to endorse or promote products derived from this software
// * without specific prior written permission.
// *
// * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
// * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
// * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
// * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
// * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
// * SUCH DAMAGE.
#include <iostream>
#include <osgViewer/Viewer>
#include <osgDB/ReadFile>
#include <osg/Node>
#include <osg/ref_ptr>
#include <osg/LightModel>
#include <osg/Geode>
#include <osg/ShapeDrawable>
#include <osg/Material>
#include <osg/Texture2D>
#include <osg/PositionAttitudeTransform>
#include <osg/Group>
#include <osg/MatrixTransform>
#include <osg/LightSource>
#include <osgShadow/ShadowedScene>
#include <osgShadow/ShadowMap>
#define LIGHT_CUTOFF_ANGLE 15
#define FILE_PATH_1 "tank.osg"
#define FILE_PATH_2 "rov.osg"
osg::Node* createLightSource(unsigned int num,
const osg::Vec3& trans,
const osg::Vec4& color)
{
osg::ref_ptr<osg::Light> light = new osg::Light;
light->setLightNum(num);
light->setDiffuse(color);
light->setPosition(osg::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
osg::ref_ptr<osg::LightSource> lightSource = new osg::LightSource;
lightSource->setLight(light);
osg::ref_ptr<osg::MatrixTransform> sourceTrans = new osg::MatrixTransform;
sourceTrans->setMatrix(osg::Matrix::translate(trans));
sourceTrans->addChild(lightSource.get());
return sourceTrans.release();
}
int main(int argc, char const *argv[])
{
// Set masks of shadow receivers and casters
unsigned int rcvShadowMask = 0x1;
unsigned int castShadowMask = 0x2;
// Tank
osg::ref_ptr<osg::MatrixTransform> tankNode = new osg::MatrixTransform;
tankNode->addChild(osgDB::readNodeFile(FILE_PATH_1));
tankNode->setMatrix(osg::Matrix::translate(0.0f, 0.0f, 0.0f));
tankNode->setNodeMask(rcvShadowMask|castShadowMask);
// ROV
osg::ref_ptr<osg::MatrixTransform> rovNode = new osg::MatrixTransform;
rovNode->addChild( osgDB::readNodeFile(FILE_PATH_2));
rovNode->setMatrix(osg::Matrix::translate(5.0f, 5.0f, -1.0f));
rovNode->setNodeMask(rcvShadowMask|castShadowMask);
// Ambient light (taken from book)
osg::ref_ptr<osg::LightSource> source0 = new osg::LightSource;
source0->getLight()->setPosition(osg::Vec4(5.0, 5.0, 9.0, 0.0));
source0->getLight()->setAmbient(osg::Vec4(0.2, 0.2, 0.2, 1.0));
source0->getLight()->setDiffuse(osg::Vec4(0.8, 0.8, 0.8, 1.0));
// We choose the famous and effective shadow mapping (osgShadow::ShadowMap) technique, and set its
// necessary parameters including the light source, shadow texture's size, and unit:
osg::ref_ptr<osgShadow::ShadowMap> sm0 = new osgShadow::ShadowMap;
sm0->setLight(source0.get());
sm0->setTextureSize(osg::Vec2s(1024, 1024));
sm0->setTextureUnit(1);
//Set the shadow scene's root node, and apply the technique instance, as well as shadow masks to it:
osg::ref_ptr<osgShadow::ShadowedScene> root = new osgShadow::ShadowedScene;
root->setShadowTechnique(sm0.get());
root->setReceivesShadowTraversalMask(rcvShadowMask);
root->setCastsShadowTraversalMask(castShadowMask);
// Create a light state set
osg::StateSet* state = root->getOrCreateStateSet();
/* state->setMode(GL_LIGHTING, osg::StateAttribute::ON);
state->setMode(GL_LIGHT0, osg::StateAttribute::ON); */
state->setMode(GL_LIGHT1, osg::StateAttribute::ON);
/* state->setMode(GL_LIGHT2, osg::StateAttribute::ON);
state->setMode(GL_LIGHT3, osg::StateAttribute::ON); */
// 1st Light Cone
osg::ref_ptr<osg::Light> light1 = new osg::Light();
light1->setAmbient(osg::Vec4(0.1, 0.1, 0.1, 0.5));
light1->setPosition(osg::Vec4(4.0, 4.0, 9.0, 1.0));
light1->setDirection(osg::Vec3(0, 0, -1));
light1->setSpotCutoff(LIGHT_CUTOFF_ANGLE);
light1->setLightNum(1);
osg::ref_ptr<osg::LightSource> source1 = new osg::LightSource();
source1->setLight(light1.get());
// We may have many lights, but only one of them will cast shadows so far.
// Uncomment the ShadowMap lines to see this behavior.
/* osg::ref_ptr<osgShadow::ShadowMap> sm1 = new osgShadow::ShadowMap;
sm1->setLight(source1.get());
sm1->setTextureSize(osg::Vec2s(1024, 1024));
sm1->setTextureUnit(1);
root->setShadowTechnique(sm1.get()); */
// Add all models and the light source to the root
root->addChild(tankNode.get());
root->addChild(rovNode.get());
root->addChild(source0.get());
root->addChild(source1.get());
// Start the viewer
osgViewer::Viewer viewer;
viewer.setSceneData(root.get());
return viewer.run();
}
Why I am not getting a shadow for every light? What am I missing here?
Thank you in advance!
You are using a wrong method for this. To allow use multiple lights use:
osgShadow::ViewDependentShadowMap* sm0 = new osgShadow::ViewDependentShadowMap;
insted of
osg::ref_ptr<osgShadow::ShadowMap> sm0 = new osgShadow::ShadowMap;
sm0->setLight(source0.get());
sm0->setTextureSize(osg::Vec2s(1024, 1024));
sm0->setTextureUnit(1);
See: http://www.openscenegraph.org/index.php/documentation/guides/programming-guides/108-shadows