Project

General

Profile

SO3Engine
SO3ShadowLiSPSM.cpp
Go to the documentation of this file.
1
10#include "SO3Renderer/SO3Root.h"
11
12namespace SO3
13{
15{
16#ifdef RPI
17 return false;
18#endif
19
20 //test if shaders are supported by the card
21 const Ogre::RenderSystemCapabilities* caps = SRoot::getSingleton().GetOgreRenderSystem()->getCapabilities();
22
23 bool isSupported = true;
24 Ogre::PixelFormat rttformat;
25
26 bool pfsupport = SRoot::getSingleton().GetRttPixelFormat(rttformat, false, true);
27
28 isSupported = pfsupport && caps && caps->hasCapability(Ogre::RSC_VERTEX_PROGRAM) &&
29 caps->hasCapability(Ogre::RSC_FRAGMENT_PROGRAM) &&
30 caps->hasCapability(Ogre::RSC_NON_POWER_OF_2_TEXTURES) &&
31 (caps->isShaderProfileSupported("ps_3_0") || caps->isShaderProfileSupported("ps_4_0") || (caps->isShaderProfileSupported("arbfp1")) || (caps->isShaderProfileSupported("glsles")) || (caps->isShaderProfileSupported("glsl300es")));
32
33 if (isSupported)
34 Ogre::LogManager::getSingleton().logMessage("[SShadowLiSPSM] is supported!");
35 else
36 Ogre::LogManager::getSingleton().logMessage("[SShadowLiSPSM] is not supported!");
37
38 return isSupported;
39}
40
41SShadowLiSPSM::SShadowLiSPSM() : SShadow(0, "", SShadowManager::SO3_SHADOWS_LISPSM)
42{
43}
44
45SShadowLiSPSM::SShadowLiSPSM(SShadowManager* sManager) : SShadow(sManager, "LiSPSM", SShadowManager::SO3_SHADOWS_LISPSM)
46{
47 ogreScene->setShadowTechnique(static_cast <Ogre::ShadowTechnique> (Ogre::SHADOWDETAILTYPE_TEXTURE | Ogre::SHADOWDETAILTYPE_INTEGRATED | shadowManager->GetLightingTechnique()));
48
49 unsigned short quality = sManager->GetShadowQuality();
50 ogreScene->setShadowTextureSelfShadow(false);
51 ogreScene->setShadowCasterRenderBackFaces(true);
52 ogreScene->setShadowTextureCount(4);
53 ogreScene->setShadowTextureFSAA(2);
54
55 ogreScene->setShadowTextureCountPerLightType(Ogre::Light::LT_SPOTLIGHT, 1);
56 ogreScene->setShadowTextureCountPerLightType(Ogre::Light::LT_DIRECTIONAL, 1);
57 ogreScene->setShadowTextureCountPerLightType(Ogre::Light::LT_POINT, 1);
58
59 //get best format on device
61
62 ogreScene->setShadowTextureSize(sManager->GetShadowQuality());
63 ogreScene->setShadowTexturePixelFormat(mRttFormat);
64
65 ogreScene->setShadowDirLightTextureOffset(0.6f);
66 ogreScene->setShadowTextureFadeStart(mFadeStart);
67 ogreScene->setShadowTextureFadeEnd(mFadeEnd);
68
69 try
70 {
71 ogreScene->setShadowTextureCasterMaterial(Ogre::MaterialManager::getSingleton().getByName("SO3/LISPSM/ShadowCaster"));
72 ogreScene->setShadowTextureReceiverMaterial(Ogre::MaterialPtr());
73 }
74 catch (Ogre::Exception &e)
75 {
76 //can fail here is a material texture is missing
77 MMechostr(MSKDEBUG, ">>> SShadowLISPSM error : %s\n", e.what());
78 }
79
80 Ogre::ShadowCameraSetupPtr shadowCameraSetup = StableLISPSMShadowCameraSetup::create();
81
82 StableLISPSMShadowCameraSetup* lispsmSetup = static_cast<StableLISPSMShadowCameraSetup*>(shadowCameraSetup.get());
83 lispsmSetup->setOptimalAdjustFactor(10.0f);
84 lispsmSetup->setCameraLightDirectionThreshold(Ogre::Degree(25.0f));
85 lispsmSetup->setUseSimpleOptimalAdjust(true);
86 //lispsmSetup->setUseAggressiveFocusRegion(false);
87
88 SetCameraSetup(shadowCameraSetup);
89
90 CreateMaterialsPass();
91}
92
94{
95 //reset to default
96 Ogre::MaterialPtr emptyMat;
97 ogreScene->setShadowTextureCasterMaterial(emptyMat);
98 ogreScene->setShadowTextureReceiverMaterial(emptyMat);
99
100 CleanMaterials();
101
102 ogreScene->setShadowTextureCount(1);
103 ogreScene->setShadowTextureCountPerLightType(Ogre::Light::LT_SPOTLIGHT, 1);
104 ogreScene->setShadowTextureCountPerLightType(Ogre::Light::LT_DIRECTIONAL, 1);
105 ogreScene->setShadowTextureCountPerLightType(Ogre::Light::LT_POINT, 1);
106 ogreScene->setShadowTexturePixelFormat(Ogre::PF_X8R8G8B8);
107 ogreScene->setShadowCasterRenderBackFaces(false);
108 ogreScene->setShadowTextureSelfShadow(true);
109 ogreScene->setShadowTechnique(Ogre::SHADOWTYPE_NONE);
110}
111
113{
114 ogreScene->setShadowTechnique(static_cast <Ogre::ShadowTechnique> (Ogre::SHADOWDETAILTYPE_TEXTURE | Ogre::SHADOWDETAILTYPE_INTEGRATED | shadowManager->GetLightingTechnique()));
115}
116
118{
119 if (pass->getName() == "LISPSM/PASS")
120 return true;
121
122 return false;
123}
124
125void SShadowLiSPSM::RemoveMaterialPass(Ogre::Technique* tech)
126{
127 if (!tech)
128 return;
129
130 //remove previous shadow pass
131 Ogre::Technique::Passes passes = tech->getPasses();
132 for (unsigned int i = 0; i < passes.size(); i++)
133 {
134 Ogre::Pass* pass = passes[i];
135 if (pass->getName() == "LISPSM/PASS")
136 {
137 tech->removePass(i);
138 break;
139 }
140 }
141
142 tech->setShadowCasterMaterial("");
143 tech->setShadowReceiverMaterial("");
144}
145
146void SShadowLiSPSM::UpdateShadowMaterial(Ogre::Technique* tech)
147{
148 if (!tech || (tech->getParent()->getName() == "Ogre/Debug/LinesMat")/* || ((tech->getSchemeName() != Ogre::MSN_SHADERGEN) &&
149 (tech->getSchemeName() != "Default") &&
150 (tech->getSchemeName() != "basic_mat"))*/)
151 return;
152
153 //remove previous pass
154 RemoveMaterialPass(tech);
155
156 // If the technique is transparent, then ignore for rendering
157 if (tech->hasColourWriteDisabled() || (!tech->getParent()->getReceiveShadows()) || (tech->getSchemeName() == "SO3/LIGHTSHAFT"))
158 return;
159
160 Ogre::Technique::Passes opasses = tech->getPasses();
161 Ogre::MaterialPtr baseMat;
162
163 //look to alpha rejection pass > 120
164 Ogre::TexturePtr alphaTex;
165 Ogre::Pass* alphaPass = 0;
166 Ogre::TextureUnitState* astate = 0;
167
168 //search for alpha texture
169 if (opasses.size() > 0)
170 {
171 Ogre::Pass* pass = opasses[0];
172 if (pass && Ogre::Real(pass->getAlphaRejectValue()) > 120.0f)
173 {
174 unsigned short nbTex = pass->getNumTextureUnitStates();
175 for (unsigned short t = 0; t < nbTex && !alphaTex; t++)
176 {
177 Ogre::TextureUnitState* ustate = pass->getTextureUnitState(t);
178 Ogre::TexturePtr texptr = ustate->_getTexturePtr();
179 if (texptr && texptr->hasAlpha() && (texptr->getTextureType() == Ogre::TEX_TYPE_2D))
180 {
181 alphaTex = texptr;
182 astate = ustate;
183 alphaPass = pass;
184 }
185 }
186 }
187 }
188
189 if (alphaTex)
190 baseMat = Ogre::MaterialManager::getSingleton().getByName("SO3/LISPSM/ShadowReceiver");
191 else
192 baseMat = Ogre::MaterialManager::getSingleton().getByName("SO3/LISPSM/ShadowReceiver/basic");
193
194 Ogre::Pass* basePass = baseMat->getTechnique(0)->getPass(0);
195
196 Ogre::Pass* nPass = tech->createPass();
197 *nPass = *basePass;
198
199 nPass->setName("LISPSM/PASS");
200 nPass->setIlluminationStage(Ogre::IS_DECAL);
201 nPass->setLightingEnabled(false);
202 nPass->setDepthBias(0.01f, 1.0f);
203 //if (GetShadowManager()->GetLightingTechnique() == SShadowManager::SO3_ADDITIVE_SHADOWS_LIGHTING)
204 // nPass->setSceneBlending(Ogre::SBT_ADD);
205 //else
206 //nPass->setSceneBlending(Ogre::SBT_ADD);
207
208 Ogre::Pass* oPass = 0;
209 if (alphaTex)
210 oPass = alphaPass;
211 else if (opasses.size() > 0)
212 oPass = opasses[0];
213
214 Ogre::Real pointSize = 1.0f;
215
216 if (oPass && !oPass->getPolygonModeOverrideable() && (oPass->getPolygonMode() == Ogre::PM_POINTS))
217 {
218 nPass->setPolygonMode(Ogre::PM_POINTS);
219 nPass->setPointSize(oPass->getPointSize());
220 }
221
222 nPass->setDiffuse(oPass->getDiffuse());
223 nPass->setAmbient(oPass->getAmbient());
224 nPass->setDepthWriteEnabled(false);
225 nPass->setAlphaRejectSettings(oPass->getAlphaRejectFunction(), oPass->getAlphaRejectValue(), false);
226
227 // add the texture with alpha
228 if (alphaTex)
229 {
230 Ogre::TextureUnitState* nTunitState = nPass->getTextureUnitState(4);
231 *nTunitState = *astate;
232 }
233
234 Ogre::MaterialPtr mcaster;
235 if (!oPass->getDepthWriteEnabled() || alphaTex)
236 {
237 if (!alphaTex)
238 {
239 try
240 {
241 mcaster = Ogre::MaterialManager::getSingleton().getByName("SO3/LISPSM/ShadowCaster")->clone("SO3/LISPSM/ShadowCaster" + tech->getParent()->getName(), tech->getParent()->getGroup());
242 }
243 catch (Ogre::Exception&)
244 {
245 mcaster = Ogre::MaterialManager::getSingleton().getByName("SO3/LISPSM/ShadowCaster" + tech->getParent()->getName());
246 }
247 }
248 else
249 {
250 try
251 {
252 mcaster = Ogre::MaterialManager::getSingleton().getByName("SO3/LISPSM/ShadowCaster/Alpha")->clone("SO3/LISPSM/ShadowCaster/Alpha" + tech->getParent()->getName(), tech->getParent()->getGroup());
253 }
254 catch (Ogre::Exception&)
255 {
256 mcaster = Ogre::MaterialManager::getSingleton().getByName("SO3/LISPSM/ShadowCaster/Alpha" + tech->getParent()->getName());
257 }
258 }
259
260 if (!mcaster.isNull() && mcaster->getTechnique(0) != 0)
261 {
262 mcaster->getTechnique(0)->getPass(0)->setDiffuse(oPass->getDiffuse());
263 mcaster->getTechnique(0)->getPass(0)->setAmbient(oPass->getAmbient());
264 if (alphaTex)
265 {
266 if (mcaster->getTechnique(0)->getPass(0)->getNumTextureUnitStates() > 0)
267 *(mcaster->getTechnique(0)->getPass(0)->getTextureUnitState(0)) = *astate;
268 else
269 *(mcaster->getTechnique(0)->getPass(0)->createTextureUnitState()) = *astate;
270 }
271 else if (mcaster->getTechnique(0)->getPass(0)->getNumTextureUnitStates() > 0)
272 mcaster->getTechnique(0)->getPass(0)->removeAllTextureUnitStates();
273 }
274 tech->setShadowCasterMaterial(mcaster);
275 }
276 else
277 {
278 tech->setShadowCasterMaterial(mcaster);
279 }
280
281 tech->getParent()->reload();
282
283 // set fogging
284 Ogre::Real shadowEnd = ogreScene->getShadowFarDistance();
285 //nPass->setFog(true, Ogre::FOG_LINEAR, Ogre::ColourValue::White, 0, shadowEnd * mFadeStart, shadowEnd * mFadeEnd);
286 Ogre::Real dstart = shadowEnd * mFadeStart;
287 Ogre::Real dend = shadowEnd * mFadeEnd;
288 Ogre::GpuProgramParametersSharedPtr sparams = nPass->getFragmentProgramParameters();
289 if (sparams)
290 {
291 sparams->setNamedConstant("fogParams", Ogre::Vector4(0.0f, dstart, dend, 1.0f / (dend - dstart)));
292 }
293}
294
295void SShadowLiSPSM::CreateMaterialsPass()
296{
297 const SGroupMaterialMap groupmatmap = (*currentScene->GetMaterials());
298 SGroupMaterialMap::const_iterator iGroupMaterialList = groupmatmap.begin();
299 while (iGroupMaterialList != groupmatmap.end())
300 {
301 const SMaterialMap matmap = (*iGroupMaterialList->second);
302 SMaterialMap::const_iterator iMaterialList = matmap.begin();
303 while (iMaterialList != matmap.end())
304 {
305 Ogre::MaterialPtr material = iMaterialList->second->getOgreMaterialPointer();
306 Ogre::Material::Techniques techniques = material->getTechniques();
307 for (unsigned int t = 0; t < techniques.size(); t++)
308 {
309 UpdateShadowMaterial(techniques[t]);
310 }
311
312 iMaterialList++;
313 }
314 iGroupMaterialList++;
315 }
316}
317
318void SShadowLiSPSM::CleanMaterials()
319{
320 // avoid a removed texture to be referenced in the shadow caster
321 Ogre::MaterialPtr caster = Ogre::MaterialManager::getSingleton().getByName("SO3/LISPSM/ShadowCaster");
322 if (caster && (caster->getNumTechniques() > 0) && (caster->getTechnique(0)->getNumPasses() > 0) && (caster->getTechnique(0)->getPass(0)->getNumTextureUnitStates() > 0))
323 {
324 caster->getTechnique(0)->getPass(0)->removeAllTextureUnitStates();
325 caster->getTechnique(0)->getPass(0)->createTextureUnitState();
326 }
327
328 const SGroupMaterialMap groupmatmap = (*currentScene->GetMaterials());
329 SGroupMaterialMap::const_iterator iGroupMaterialList = groupmatmap.begin();
330 while (iGroupMaterialList != groupmatmap.end())
331 {
332 const SMaterialMap matmap = (*iGroupMaterialList->second);
333 SMaterialMap::const_iterator iMaterialList = matmap.begin();
334 while (iMaterialList != matmap.end())
335 {
336 Ogre::MaterialPtr material = iMaterialList->second->getOgreMaterialPointer();
338
339 //remove the shadow passs
340 Ogre::Material::Techniques techniques = material->getTechniques();
341 for (unsigned int t = 0; t < techniques.size(); t++)
342 {
343 RemoveMaterialPass(techniques[t]);
344 material->reload();
345 }
346
347 iMaterialList++;
348 }
349 iGroupMaterialList++;
350 }
351}
352
356//---------------------------------------------------------------------
360//---------------------------------------------------------------------
361void StableLISPSMShadowCameraSetup::getShadowCamera(const Ogre::SceneManager *sm, const Ogre::Camera *cam, const Ogre::Viewport *vp, const Ogre::Light *light, Ogre::Camera *texCam, size_t iteration) const
362{
363 Ogre::Camera* _cam = const_cast<Ogre::Camera*>(cam);
364 Ogre::Real oldNear = _cam->getNearClipDistance();
365 Ogre::Real oldFar = _cam->getFarClipDistance();
366 Ogre::Radian oldFovY = _cam->getFOVy();
367 Ogre::Matrix4 oldMatrix = _cam->getProjectionMatrix();
368 bool iscustom = _cam->isCustomProjectionMatrixEnabled();
369
370 _cam->setNearClipDistance(std::max(oldNear, 0.1f));
371 _cam->setFarClipDistance(std::min(sm->getShadowFarDistance(), oldFar));
372
373 if (light->getType() != Ogre::Light::LT_DIRECTIONAL)
374 {
375 float range = light->getAttenuationRange();
376 _cam->setFarClipDistance(std::min(sm->getShadowFarDistance(), range * range));
377 }
378
379 if (iscustom)
380 {
381 Ogre::Matrix4 projmat = _cam->getProjectionMatrix();
382 Ogre::Radian nCamFov = Ogre::Radian(Ogre::Math::ATan(1.0f / projmat[1][1]) * 2.0f);
383 _cam->setCustomProjectionMatrix(false);
384 _cam->setFOVy(nCamFov);
385 }
386
387 //force culling with new cam settings
388 auto cullCam = dynamic_cast<Ogre::Camera*>(texCam->getCullingFrustum());
389 Ogre::FocusedShadowCameraSetup::getShadowCamera(sm, cam, vp, light, cullCam, iteration);
390
391 Ogre::LiSPSMShadowCameraSetup::getShadowCamera(sm, cam, vp, light, texCam, iteration);
392
393 // restore near/far
394 _cam->setNearClipDistance(oldNear);
395 _cam->setFarClipDistance(oldFar);
396 _cam->setFOVy(oldFovY);
397 if (iscustom)
398 _cam->setCustomProjectionMatrix(true, oldMatrix);
399}
400
401}
MMechostr(MSKDEBUG, " > Start loading Plugin SO3Engine dll\n")
bool GetRttPixelFormat(Ogre::PixelFormat &format, bool alpha=false, bool floattex=false)
Definition SO3Root.cpp:650
Ogre::RenderSystem * GetOgreRenderSystem()
Definition SO3Root.cpp:865
void RemoveGeneratedMaterial(Ogre::Material *mat)
Definition SO3Root.cpp:2343
static SRoot & getSingleton()
Definition SO3Root.cpp:116
static SRoot * getSingletonPtr()
Definition SO3Root.cpp:111
const SMaterialMap * GetMaterials(const std::string &groupName)
Ogre::Real mFadeStart
Definition SO3Shadow.h:80
Ogre::Real mFadeEnd
Definition SO3Shadow.h:81
SShadowManager * shadowManager
Definition SO3Shadow.h:75
Ogre::SceneManager * ogreScene
Definition SO3Shadow.h:74
void SetCameraSetup(Ogre::ShadowCameraSetupPtr shadowCameraSetup)
Definition SO3Shadow.cpp:57
Ogre::PixelFormat mRttFormat
Definition SO3Shadow.h:77
SScene * currentScene
Definition SO3Shadow.h:73
virtual void RemoveMaterialPass(Ogre::Technique *tech)
virtual void UpdateShadowMaterial(Ogre::Technique *tech)
virtual void UpdateShadowTechnique()
static bool CheckSystemCompatibility()
virtual bool IsShadowMaterialPass(Ogre::Pass *pass)
ShadowLightingType GetLightingTechnique()
ShadowQuality GetShadowQuality()
void getShadowCamera(const Ogre::SceneManager *sm, const Ogre::Camera *cam, const Ogre::Viewport *vp, const Ogre::Light *light, Ogre::Camera *texCam, size_t iteration) const override
StableLISPSMShadowCameraSetup()
Constructor, defaults to 3 splits.
static Ogre::ShadowCameraSetupPtr create()
std::unordered_map< std::string, SMaterial * > SMaterialMap
std::unordered_map< std::string, SMaterialMap * > SGroupMaterialMap