[790] | 1 | #include "OgreDepthShadowMapRenderingRun.h"
|
---|
[1055] | 2 | #include "OgreIlluminationManager.h"
|
---|
[790] | 3 |
|
---|
| 4 |
|
---|
| 5 | OgreDepthShadowMapRenderingRun::OgreDepthShadowMapRenderingRun(OgreSharedRuns* sharedRuns,
|
---|
| 6 | String name,
|
---|
| 7 | Light* light,
|
---|
| 8 | unsigned int resolutionX,
|
---|
| 9 | unsigned int resolutionY,
|
---|
| 10 | String materialName
|
---|
| 11 | )
|
---|
| 12 | :DepthShadowMapRenderingRun(resolutionX, resolutionY)
|
---|
[874] | 13 | , OgreRenderingRun(1, 1)
|
---|
| 14 | , RenderingRun(1, 1)
|
---|
[790] | 15 | {
|
---|
| 16 | this->light = light;
|
---|
| 17 | this->sharedRuns = sharedRuns;
|
---|
[1120] | 18 | this->name = name;
|
---|
[1130] | 19 | this->blurredname = name + "blurred";
|
---|
[1120] | 20 |
|
---|
[790] | 21 | this->materialName = materialName;
|
---|
[1670] | 22 | lightFarPlane = 0;
|
---|
[790] | 23 | createDepthMap();
|
---|
| 24 | }
|
---|
| 25 |
|
---|
| 26 | void OgreDepthShadowMapRenderingRun::createDepthMap()
|
---|
| 27 | {
|
---|
[1120] | 28 |
|
---|
| 29 | TexturePtr texPtr = Ogre::TextureManager::getSingleton().createManual(name,
|
---|
[1055] | 30 | "default",
|
---|
| 31 | TEX_TYPE_2D,
|
---|
| 32 | resolutionX,
|
---|
| 33 | resolutionY,
|
---|
| 34 | 0,
|
---|
| 35 | 0,
|
---|
| 36 | PF_FLOAT16_RGBA,
|
---|
[1130] | 37 | TU_RENDERTARGET);
|
---|
[1120] | 38 | depthMapTexture = texPtr.getPointer();
|
---|
| 39 | depthMapCamera = Root::getSingleton()._getCurrentSceneManager()->createCamera(name + "_CAMERA");
|
---|
[1055] | 40 | //add viewport to rendertarget
|
---|
[1120] | 41 | HardwarePixelBuffer* hpb = (depthMapTexture->getBuffer()).getPointer();
|
---|
[1055] | 42 | RenderTarget* rt = hpb->getRenderTarget();
|
---|
[1120] | 43 | Viewport* v = rt->addViewport(depthMapCamera);
|
---|
[1628] | 44 | v->setBackgroundColour(ColourValue::White);
|
---|
[1055] | 45 | v->setOverlaysEnabled(false);
|
---|
[1130] | 46 | rt->setAutoUpdated(false);
|
---|
[1628] | 47 |
|
---|
| 48 | if(OgreIlluminationManager::getSingleton().getBlurShadowMap())
|
---|
| 49 | {
|
---|
| 50 | texPtr = Ogre::TextureManager::getSingleton().createManual(blurredname,
|
---|
| 51 | "default",
|
---|
| 52 | TEX_TYPE_2D,
|
---|
| 53 | resolutionX,
|
---|
| 54 | resolutionY,
|
---|
| 55 | 6,
|
---|
| 56 | 0,
|
---|
| 57 | PF_FLOAT16_RGBA,
|
---|
| 58 | TU_RENDERTARGET);
|
---|
| 59 | blurredDepthMapTexture = texPtr.getPointer();
|
---|
| 60 | hpb = (blurredDepthMapTexture->getBuffer()).getPointer();
|
---|
| 61 | rt = hpb->getRenderTarget();
|
---|
| 62 | v = rt->addViewport(depthMapCamera);
|
---|
| 63 | v->setOverlaysEnabled(false);
|
---|
| 64 | rt->setAutoUpdated(false);
|
---|
| 65 | }
|
---|
[790] | 66 | }
|
---|
| 67 |
|
---|
| 68 | void OgreDepthShadowMapRenderingRun::updateFrame(unsigned long frameNum)
|
---|
| 69 | {
|
---|
[1103] | 70 | refreshLight(frameNum);
|
---|
[790] | 71 |
|
---|
| 72 | if(light->getType() == Light::LT_POINT)
|
---|
| 73 | {
|
---|
| 74 | updateDepthMap();
|
---|
| 75 | }
|
---|
| 76 | else
|
---|
| 77 | {
|
---|
| 78 | updateDepthMap();
|
---|
[1130] | 79 | }
|
---|
[790] | 80 | }
|
---|
| 81 |
|
---|
| 82 | void OgreDepthShadowMapRenderingRun::updateDepthCubeFace(int facenum)
|
---|
| 83 | {
|
---|
| 84 | }
|
---|
| 85 |
|
---|
| 86 | void OgreDepthShadowMapRenderingRun::updateDepthMap()
|
---|
| 87 | {
|
---|
[1120] | 88 | setMaterialForVisibles(materialName, depthMapCamera, false);
|
---|
| 89 | RenderTarget* rt = depthMapTexture->getBuffer().getPointer()->getRenderTarget();
|
---|
| 90 | Viewport* vp = rt->getViewport(0);
|
---|
| 91 |
|
---|
[1055] | 92 | rt->update();
|
---|
| 93 | restoreMaterials();
|
---|
[1130] | 94 |
|
---|
[1628] | 95 | if(OgreIlluminationManager::getSingleton().getBlurShadowMap())
|
---|
| 96 | {
|
---|
| 97 | rt = blurredDepthMapTexture->getBuffer().getPointer()->getRenderTarget();
|
---|
| 98 | Material* mat = (Material*) MaterialManager::getSingleton().getByName("GameTools/Blur").getPointer();
|
---|
| 99 | mat->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setTextureName(depthMapTexture->getName());
|
---|
| 100 | renderFullscreenQuad("GameTools/Blur", rt);
|
---|
| 101 | }
|
---|
[1130] | 102 |
|
---|
| 103 | //rt->writeContentsToFile("shadowmap1.dds");
|
---|
| 104 |
|
---|
| 105 | //depthMapTexture->();
|
---|
[1055] | 106 | }
|
---|
[1688] | 107 |
|
---|
| 108 | const String& OgreDepthShadowMapRenderingRun::getDepthMapTextureName()
|
---|
[1055] | 109 | {
|
---|
[1628] | 110 | if(OgreIlluminationManager::getSingleton().getBlurShadowMap())
|
---|
| 111 | return blurredname;
|
---|
[790] | 112 |
|
---|
[1628] | 113 | return name;
|
---|
[790] | 114 | }
|
---|
| 115 |
|
---|
[1103] | 116 | void OgreDepthShadowMapRenderingRun::refreshLight(unsigned long frameNum)
|
---|
[790] | 117 | {
|
---|
| 118 |
|
---|
| 119 | if(light!= 0)
|
---|
| 120 | {
|
---|
[1628] | 121 | bool uselispsm = OgreIlluminationManager::getSingleton().getUseLISPSM();
|
---|
[1639] | 122 | bool usefocusing = OgreIlluminationManager::getSingleton().getFocusingShadowMap();
|
---|
[790] | 123 | if(light->getType() == Light::LT_DIRECTIONAL)
|
---|
| 124 | {
|
---|
[1125] | 125 | Camera* viewcam = OgreIlluminationManager::getSingleton().getMainCamera();
|
---|
[1055] | 126 |
|
---|
[1103] | 127 | OgreFocusingMapRenderingRun* frun = (OgreFocusingMapRenderingRun*)
|
---|
[1125] | 128 | OgreIlluminationManager::getSingleton().getGlobalRun(ILLUMRUN_FOCUSING_MAP)->asOgreRenderingRun();
|
---|
| 129 | frun->setCameraMatrices(viewcam->getViewMatrix(), viewcam->getProjectionMatrix());
|
---|
[1055] | 130 |
|
---|
[1628] | 131 | Vector3 lightpos = light->getParentSceneNode()->getWorldPosition();
|
---|
[1103] | 132 | Vector3 lightdir = light->getDirection();
|
---|
[1125] | 133 | lightdir.normalise();
|
---|
| 134 |
|
---|
| 135 | Vector3 min;
|
---|
| 136 | Vector3 max;
|
---|
[1055] | 137 |
|
---|
[1628] | 138 |
|
---|
[1125] | 139 | if(uselispsm)
|
---|
| 140 | {
|
---|
| 141 | Camera* maincam = OgreIlluminationManager::getSingleton().getMainCamera();
|
---|
| 142 | Vector3 viewdir = maincam->getDirection();
|
---|
| 143 | viewdir.normalise();
|
---|
| 144 | Vector3 campos = maincam->getPosition();
|
---|
| 145 | float nearclip = maincam->getNearClipDistance();
|
---|
[1055] | 146 |
|
---|
[1125] | 147 | float dotprod = viewdir.dotProduct(lightdir);
|
---|
| 148 | float sinGamma = sqrt(1.0 - dotprod * dotprod);
|
---|
| 149 |
|
---|
| 150 | Vector3 left = lightdir.crossProduct(viewdir);
|
---|
[1628] | 151 | left.normalise();
|
---|
[1125] | 152 | Vector3 up = left.crossProduct(lightdir);
|
---|
| 153 | up.normalise();
|
---|
| 154 | //left = lightdir.crossProduct(up);
|
---|
| 155 | left.normalise();
|
---|
| 156 | Matrix4 viewMatrix( left.x, left.y, left.z, 0,
|
---|
| 157 | up.x, up.y, up.z, 0,
|
---|
| 158 | lightdir.x, lightdir.y, lightdir.z, 0,
|
---|
| 159 | 0, 0, 0, 1);
|
---|
| 160 |
|
---|
| 161 | frun->setLightMatrix(viewMatrix);
|
---|
| 162 | OgreIlluminationManager::getSingleton().updateGlobalRun( ILLUMRUN_FOCUSING_MAP,
|
---|
| 163 | frameNum);
|
---|
| 164 | frun->getMinMax(min, max);
|
---|
| 165 |
|
---|
| 166 | float n;
|
---|
| 167 | float f;
|
---|
| 168 | float d = abs(max.y - min.y);
|
---|
| 169 |
|
---|
| 170 | float z_n = nearclip / sinGamma;
|
---|
| 171 | float one_min_singamma = (1 - sinGamma);
|
---|
| 172 | float fact = d * pow(one_min_singamma, 2);
|
---|
| 173 | float z_f = z_n + d * sinGamma * fact;
|
---|
| 174 | n = (z_n + sqrt(z_f * z_n)) / sinGamma;
|
---|
| 175 | ///n = 100000;
|
---|
| 176 | f = n + d;
|
---|
| 177 |
|
---|
| 178 | Vector3 pos = campos - up * (n - nearclip);
|
---|
| 179 | Matrix4 newViewMatrix( left.x, left.y, left.z, -left.dotProduct(pos),
|
---|
| 180 | up.x, up.y, up.z, -up.dotProduct(pos),
|
---|
[1628] | 181 | -lightdir.x, -lightdir.y, -lightdir.z, lightdir.dotProduct(pos),
|
---|
[1125] | 182 | 0, 0, 0, 1);
|
---|
| 183 |
|
---|
[1130] | 184 | Matrix4 lispMat = Matrix4::IDENTITY;
|
---|
[1125] | 185 |
|
---|
[1130] | 186 | lispMat[1][1] = f / (f - n);
|
---|
| 187 | lispMat[1][3] = f * n / (f - n);
|
---|
| 188 | lispMat[3][1] = 1;
|
---|
| 189 | lispMat[3][3] = 0;
|
---|
| 190 |
|
---|
| 191 | depthMapCamera->setCustomProjectionMatrix(true, Matrix4::IDENTITY);
|
---|
| 192 | depthMapCamera->setCustomViewMatrix(true, lispMat * newViewMatrix);
|
---|
[1125] | 193 | }
|
---|
| 194 | else
|
---|
| 195 | {
|
---|
[1130] | 196 | depthMapCamera->setCustomProjectionMatrix(true, Matrix4::IDENTITY);
|
---|
[1125] | 197 | depthMapCamera->setCustomViewMatrix(false);
|
---|
| 198 | depthMapCamera->setPosition(lightpos);
|
---|
[1130] | 199 | depthMapCamera->setDirection(lightdir);
|
---|
[1125] | 200 | }
|
---|
| 201 |
|
---|
| 202 |
|
---|
[1130] | 203 | Matrix4 lightMatrix = depthMapCamera->getViewMatrix();
|
---|
[1125] | 204 | frun->setLightMatrix(lightMatrix);
|
---|
[1120] | 205 |
|
---|
[1125] | 206 | OgreIlluminationManager::getSingleton().updateGlobalRun( ILLUMRUN_FOCUSING_MAP,
|
---|
| 207 | frameNum);
|
---|
| 208 |
|
---|
| 209 | frun->getMinMax(min, max);
|
---|
| 210 |
|
---|
| 211 |
|
---|
[1120] | 212 | Vector3 scale = (max - min);
|
---|
[1125] | 213 | scale *= 1.5; // just for safety
|
---|
[1628] | 214 | if(uselispsm)
|
---|
| 215 | scale.z += 1;
|
---|
| 216 | else
|
---|
| 217 | scale.z += 1000; //TODO: get scene bounding box to set z scale
|
---|
[1125] | 218 | Matrix4 projection = Matrix4::IDENTITY;
|
---|
[1628] | 219 | Matrix4 trans = Matrix4::IDENTITY;
|
---|
| 220 | trans.setTrans(Vector3(-(max.x + min.x) / 2.0,
|
---|
| 221 | -(max.y + min.y) / 2.0,
|
---|
| 222 | -(max.z + min.z) / 2.0));
|
---|
| 223 | Matrix4 scaleM = Matrix4::IDENTITY;
|
---|
| 224 | scaleM.setScale(Vector3(2.0 / scale.x, 2.0 / scale.y, -2.0 / scale.z));
|
---|
| 225 | projection = scaleM * trans;
|
---|
[1130] | 226 | depthMapCamera->setCustomProjectionMatrix(true, projection);
|
---|
[790] | 227 | }
|
---|
| 228 | else if(light->getType() == Light::LT_SPOTLIGHT)
|
---|
| 229 | {
|
---|
[1628] | 230 | Camera* viewcam = OgreIlluminationManager::getSingleton().getMainCamera();
|
---|
| 231 |
|
---|
| 232 | OgreFocusingMapRenderingRun* frun = (OgreFocusingMapRenderingRun*)
|
---|
| 233 | OgreIlluminationManager::getSingleton().getGlobalRun(ILLUMRUN_FOCUSING_MAP)->asOgreRenderingRun();
|
---|
| 234 | frun->setCameraMatrices(viewcam->getViewMatrix(), viewcam->getProjectionMatrix());
|
---|
| 235 |
|
---|
| 236 | Vector3 lightpos = light->getParentSceneNode()->getWorldPosition ();
|
---|
| 237 | Vector3 lightdir = light->getDirection();
|
---|
| 238 | lightdir.normalise();
|
---|
| 239 | Radian lightangle = light->getSpotlightOuterAngle();
|
---|
| 240 |
|
---|
| 241 | Vector3 min;
|
---|
| 242 | Vector3 max;
|
---|
| 243 |
|
---|
| 244 | if(uselispsm)
|
---|
| 245 | {
|
---|
| 246 | Camera* maincam = OgreIlluminationManager::getSingleton().getMainCamera();
|
---|
| 247 | Vector3 viewdir = maincam->getDirection();
|
---|
| 248 | viewdir.normalise();
|
---|
| 249 | Vector3 campos = maincam->getPosition();
|
---|
| 250 | float nearclip = maincam->getNearClipDistance();
|
---|
| 251 |
|
---|
| 252 | float dotprod = viewdir.dotProduct(lightdir);
|
---|
| 253 | float sinGamma = sqrt(1.0 - dotprod * dotprod);
|
---|
| 254 |
|
---|
| 255 | Vector3 left = lightdir.crossProduct(viewdir);
|
---|
| 256 | Vector3 up = left.crossProduct(lightdir);
|
---|
| 257 | up.normalise();
|
---|
| 258 | //left = lightdir.crossProduct(up);
|
---|
| 259 | left.normalise();
|
---|
| 260 |
|
---|
| 261 | depthMapCamera->setCustomProjectionMatrix(false);
|
---|
| 262 | depthMapCamera->setProjectionType(PT_PERSPECTIVE);
|
---|
| 263 | depthMapCamera->setFOVy(lightangle);
|
---|
| 264 | depthMapCamera->setAspectRatio(1);
|
---|
| 265 | depthMapCamera->setNearClipDistance(0.1);
|
---|
| 266 | depthMapCamera->setFarClipDistance(1.0);
|
---|
| 267 |
|
---|
| 268 | Matrix4 projMatrix = depthMapCamera->getProjectionMatrixWithRSDepth();
|
---|
| 269 |
|
---|
| 270 | Matrix4 viewMatrix( left.x, left.y, left.z, 0,
|
---|
| 271 | up.x, up.y, up.z, 0,
|
---|
| 272 | -lightdir.x, -lightdir.y, -lightdir.z, 0,
|
---|
| 273 | 0, 0, 0, 1);
|
---|
| 274 |
|
---|
| 275 | frun->setLightMatrix(projMatrix * viewMatrix);
|
---|
| 276 | OgreIlluminationManager::getSingleton().updateGlobalRun( ILLUMRUN_FOCUSING_MAP,
|
---|
| 277 | frameNum);
|
---|
| 278 | frun->getMinMax(min, max);
|
---|
| 279 |
|
---|
| 280 | float n;
|
---|
| 281 | float f;
|
---|
| 282 | float d = abs(max.y - min.y);
|
---|
| 283 |
|
---|
| 284 | float z_n = nearclip / sinGamma;
|
---|
| 285 | float one_min_singamma = (1 - sinGamma);
|
---|
| 286 | float fact = d * pow(one_min_singamma, 2);
|
---|
| 287 | float z_f = z_n + d * sinGamma * fact;
|
---|
| 288 | n = (z_n + sqrt(z_f * z_n)) / sinGamma;
|
---|
| 289 | ///n = 100000;
|
---|
| 290 | f = n + d;
|
---|
| 291 |
|
---|
| 292 | Vector3 pos = campos - up * (n - nearclip);
|
---|
| 293 | Matrix4 newViewMatrix( left.x, left.y, left.z, -left.dotProduct(pos),
|
---|
| 294 | up.x, up.y, up.z, -up.dotProduct(pos),
|
---|
| 295 | -lightdir.x, -lightdir.y, -lightdir.z, lightdir.dotProduct(pos),
|
---|
| 296 | 0, 0, 0, 1);
|
---|
| 297 |
|
---|
| 298 | Matrix4 lispMat = Matrix4::IDENTITY;
|
---|
| 299 |
|
---|
| 300 | lispMat[1][1] = f / (f - n);
|
---|
| 301 | lispMat[1][3] = f * n / (f - n);
|
---|
| 302 | lispMat[3][1] = 1;
|
---|
| 303 | lispMat[3][3] = 0;
|
---|
| 304 |
|
---|
| 305 | depthMapCamera->setCustomProjectionMatrix(true, Matrix4::IDENTITY);
|
---|
| 306 | depthMapCamera->setCustomViewMatrix(true, lispMat * projMatrix * newViewMatrix);
|
---|
| 307 | }
|
---|
| 308 | else
|
---|
| 309 | {
|
---|
| 310 | depthMapCamera->setCustomProjectionMatrix(false);
|
---|
| 311 | depthMapCamera->setCustomViewMatrix(false);
|
---|
| 312 | depthMapCamera->setPosition(lightpos);
|
---|
| 313 | depthMapCamera->setDirection(lightdir);
|
---|
| 314 | depthMapCamera->setProjectionType(PT_PERSPECTIVE);
|
---|
| 315 | depthMapCamera->setFOVy(lightangle);
|
---|
| 316 | depthMapCamera->setAspectRatio(1);
|
---|
| 317 | depthMapCamera->setNearClipDistance(0.1);
|
---|
| 318 | depthMapCamera->setFarClipDistance(1.0);
|
---|
| 319 | }
|
---|
| 320 |
|
---|
[1639] | 321 | if(!usefocusing)
|
---|
[1628] | 322 | {
|
---|
[1670] | 323 | lightFarPlane = light->getAttenuationRange();
|
---|
| 324 | depthMapCamera->setFarClipDistance(lightFarPlane);
|
---|
| 325 |
|
---|
[1639] | 326 | }
|
---|
| 327 | else
|
---|
| 328 | {
|
---|
| 329 | Matrix4 lightMatrix = depthMapCamera->getViewMatrix();
|
---|
| 330 | frun->setLightMatrix(lightMatrix);
|
---|
| 331 |
|
---|
| 332 | OgreIlluminationManager::getSingleton().updateGlobalRun( ILLUMRUN_FOCUSING_MAP,
|
---|
| 333 | frameNum);
|
---|
[1628] | 334 |
|
---|
[1639] | 335 | frun->getMinMax(min, max);
|
---|
[1628] | 336 |
|
---|
[1639] | 337 | if(min.z < 0)
|
---|
| 338 | {
|
---|
| 339 | float farP= -1.5 * min.z;
|
---|
| 340 | if(farP < 0.2) farP = 0.2;
|
---|
[1670] | 341 | depthMapCamera->setFarClipDistance(farP);
|
---|
| 342 | lightFarPlane = farP;
|
---|
| 343 |
|
---|
[1639] | 344 | Vector3 scale = (max - min);
|
---|
| 345 | scale *= 1.5; // just for safety
|
---|
| 346 |
|
---|
| 347 | Matrix4 projection = Matrix4::IDENTITY;
|
---|
| 348 | Matrix4 trans = Matrix4::IDENTITY;
|
---|
| 349 | trans.setTrans(Vector3(-(max.x + min.x) / 2.0,
|
---|
| 350 | -(max.y + min.y) / 2.0,
|
---|
| 351 | 0));
|
---|
| 352 | Matrix4 scaleM = Matrix4::IDENTITY;
|
---|
| 353 | scaleM.setScale(Vector3(2.0 / scale.x, 2.0 / scale.y, 1));
|
---|
| 354 | projection = scaleM * trans;
|
---|
| 355 | depthMapCamera->setCustomProjectionMatrix(true, projection * depthMapCamera->getProjectionMatrix());
|
---|
| 356 | }
|
---|
[1628] | 357 | }
|
---|
[790] | 358 | }
|
---|
| 359 | else//point light
|
---|
| 360 | {
|
---|
[1055] | 361 | /* Vector3 pos = light->getParentNode()->getWorldPosition();
|
---|
[790] | 362 | Vector3 dir = -pos;
|
---|
| 363 | depthMapCamera->setDirection( dir );
|
---|
| 364 | depthMapCamera->setPosition(pos);
|
---|
| 365 | depthMapCamera->setProjectionType(PT_PERSPECTIVE);
|
---|
| 366 | depthMapCamera->setFOVy(Radian(Degree(140)));
|
---|
| 367 | depthMapCamera->setNearClipDistance(1);
|
---|
| 368 | // depthMapCamera->setFarClipDistance(200);
|
---|
| 369 |
|
---|
| 370 | //OGRE_EXCEPT(0, "NOT implemented for Pointlight", "OgreDepthShadowMapRenderingRun::refreshLight");
|
---|
[1055] | 371 | */
|
---|
[790] | 372 | /*Vector3 pos = light->getParentNode()->getWorldPosition();
|
---|
| 373 | Vector3 dir = -pos;
|
---|
| 374 | depthMapCamera->setDirection( dir );
|
---|
| 375 | depthMapCamera->setPosition(pos);
|
---|
| 376 | depthMapCamera->setProjectionType(PT_ORTHOGRAPHIC);
|
---|
| 377 | depthMapCamera->*/
|
---|
| 378 |
|
---|
| 379 | }
|
---|
| 380 | }
|
---|
| 381 | }
|
---|
| 382 |
|
---|
[1120] | 383 | Matrix4 OgreDepthShadowMapRenderingRun::getLightViewMatrix()
|
---|
[790] | 384 | {
|
---|
[1120] | 385 | return depthMapCamera->getViewMatrix();
|
---|
[790] | 386 | }
|
---|
| 387 |
|
---|
[1120] | 388 | Matrix4 OgreDepthShadowMapRenderingRun::getLightViewProjMatrix()
|
---|
[790] | 389 | {
|
---|
[1120] | 390 | return depthMapCamera->getProjectionMatrixWithRSDepth() * depthMapCamera->getViewMatrix();
|
---|
[790] | 391 | }
|
---|
| 392 |
|
---|