void ShaderEffect::draw (QPainter *painter) { const QGLContext *context = QGLContext::currentContext(); prepareBufferedDraw(painter); if (context) { updateRenderTargets(); } if (!context || m_renderTargets.count() == 0 || !hideOriginal()) drawSource(painter); }
void ShaderShadowMapEngine::handleSpotLightEnter( SpotLight *spotL, RenderAction *ract, SSMEngineData *data) { RenderPartition *parentPart = ract->getActivePartition(); // Real cosSpotCutOff = osgCos(spotL->getSpotCutOff()); Matrix matEyeToWorld (parentPart->getCameraToWorld()); Matrix matWorldToLight; Matrix matEyeToLight; calcSpotLightMatrices(matWorldToLight, matEyeToLight, spotL, matEyeToWorld ); Real32 lightNear; Real32 lightFar; calcPointLightRange(spotL, 0.001f, parentPart->getNear(), parentPart->getFar(), lightNear, lightFar ); if(getShadowNear() != 0.f) { lightNear = getShadowNear(); } if(getShadowFar() != 0.f) { lightFar = getShadowFar(); } Matrix matLightProj; Matrix matLightProjTrans; MatrixPerspective(matLightProj, spotL->getSpotCutOff(), 1.f, lightNear, lightFar ); updateShadowTexImage (data); updateShadowTexBuffers(data); updateRenderTargets (data); Int32 shadowTexUnit = (this->getForceTextureUnit() > 0) ? this->getForceTextureUnit() : 7; ShaderProgram *shadowFP = this->getShadowFragmentProgram(); if(shadowFP == NULL) { ShaderProgramUnrecPtr newShadowFP = ShaderProgram::createLocal(); newShadowFP->setShaderType(GL_FRAGMENT_SHADER); newShadowFP->setProgram (_spotFPCode ); newShadowFP->addUniformVariable("SSME_matEyeToLight", matEyeToLight); newShadowFP->addUniformVariable("SSME_matLightProj", matLightProj ); newShadowFP->addUniformVariable("SSME_texShadow", shadowTexUnit); this->setShadowFragmentProgram(newShadowFP); shadowFP = newShadowFP; } else { shadowFP->updateUniformVariable("SSME_matEyeToLight", matEyeToLight); shadowFP->updateUniformVariable("SSME_matLightProj", matLightProj ); } commitChanges(); this->pushPartition(ract); { RenderPartition *part = ract->getActivePartition( ); Window *win = ract->getWindow ( ); FrameBufferObject *target = data->getRenderTargets (0); Background *back = data->getBackground ( ); part->setRenderTarget(target); part->setWindow (win ); part->calcViewportDimension(0.f, 0.f, 1.f, 1.f, target->getWidth (), target->getHeight() ); part->setupProjection(matLightProj, matLightProjTrans); part->setupViewing (matWorldToLight ); part->setNear (parentPart->getNear()); part->setFar (parentPart->getFar ()); part->calcFrustum ( ); part->setBackground (back ); // force material for shadow map generation part->overrideMaterial(data->getLightPassMaterials(0), ract->getActNode ( ) ); this->recurseFrom(ract, spotL); ract->useNodeList(false ); // undo override part->overrideMaterial(NULL, ract->getActNode ( ) ); } this->popPartition(ract); }
void ShaderShadowMapEngine::handleDirectionalLightEnter( DirectionalLight *dirL, RenderAction *ract, SSMEngineData *data) { RenderPartition *parentPart = ract ->getActivePartition(); FrustumVolume camFrust = parentPart->getFrustum (); Matrix matEyeToWorld (parentPart->getCameraToWorld()); Matrix matWorldToLight; Matrix matEyeToLight; calcDirectionalLightMatrices(matWorldToLight, matEyeToLight, dirL, matEyeToWorld ); // place light camera outside the scene bounding box: // - project camera frustum and scene bounding box into a // coordinate system where the directional light shines // along the -z axis. // - compute 2 AABBs that contain the projected frustum and // scene BB // - width and height of the ortho projection are determined from // the frustum AABB, while near and far are determined by the // scene AABB (offscreen objects cast shadows into the view volume) Pnt3f camVerts [10]; Pnt3f sceneVerts[10]; const Matrix &matSceneToWorld = ract->topMatrix (); BoxVolume sceneBB = ract->getActNode()->getVolume(); camFrust.getCorners(camVerts [0], camVerts [1], camVerts [2], camVerts [3], camVerts [4], camVerts [5], camVerts [6], camVerts [7] ); sceneBB .getCorners(sceneVerts[0], sceneVerts[1], sceneVerts[2], sceneVerts[3], sceneVerts[4], sceneVerts[5], sceneVerts[6], sceneVerts[7] ); camVerts [8].setValues(TypeTraits<Real32>::getMax(), TypeTraits<Real32>::getMax(), TypeTraits<Real32>::getMax() ); camVerts [9].setValues(TypeTraits<Real32>::getMin(), TypeTraits<Real32>::getMin(), TypeTraits<Real32>::getMin() ); sceneVerts[8].setValues(TypeTraits<Real32>::getMax(), TypeTraits<Real32>::getMax(), TypeTraits<Real32>::getMax() ); sceneVerts[9].setValues(TypeTraits<Real32>::getMin(), TypeTraits<Real32>::getMin(), TypeTraits<Real32>::getMin() ); for(UInt32 i = 0; i < 8; ++i) { matWorldToLight.mult(camVerts [i], camVerts [i]); matSceneToWorld.mult(sceneVerts[i], sceneVerts[i]); matWorldToLight.mult(sceneVerts[i], sceneVerts[i]); camVerts [8][0] = osgMin(camVerts [8][0], camVerts [i][0]); camVerts [9][0] = osgMax(camVerts [9][0], camVerts [i][0]); camVerts [8][1] = osgMin(camVerts [8][1], camVerts [i][1]); camVerts [9][1] = osgMax(camVerts [9][1], camVerts [i][1]); sceneVerts[8][0] = osgMin(sceneVerts[8][0], sceneVerts[i][0]); sceneVerts[9][0] = osgMax(sceneVerts[9][0], sceneVerts[i][0]); sceneVerts[8][1] = osgMin(sceneVerts[8][1], sceneVerts[i][1]); sceneVerts[9][1] = osgMax(sceneVerts[9][1], sceneVerts[i][1]); sceneVerts[8][2] = osgMin(sceneVerts[8][2], sceneVerts[i][2]); sceneVerts[9][2] = osgMax(sceneVerts[9][2], sceneVerts[i][2]); } // these points are the corners of the ortho shadow view volume Pnt3f lightMin(osgMax(camVerts[8][0], sceneVerts[8][0]), osgMax(camVerts[8][1], sceneVerts[8][1]), -sceneVerts[9][2]); Pnt3f lightMax(osgMin(camVerts[9][0], sceneVerts[9][0]), osgMin(camVerts[9][1], sceneVerts[9][1]), -sceneVerts[8][2]); // enlarge by 2% in x, y, z direction lightMin[0] -= (lightMax[0] - lightMin[0]) * 0.01f; lightMin[1] -= (lightMax[1] - lightMin[1]) * 0.01f; lightMin[2] -= (lightMax[2] - lightMin[2]) * 0.01f; lightMax[0] += (lightMax[0] - lightMin[0]) * 0.01f; lightMax[1] += (lightMax[1] - lightMin[1]) * 0.01f; lightMax[2] += (lightMax[2] - lightMin[2]) * 0.01f; Matrix matLightProj; Matrix matLightProjTrans; MatrixOrthogonal(matLightProj, lightMin[0], lightMax[0], lightMin[1], lightMax[1], lightMin[2], lightMax[2] ); updateShadowTexImage (data); updateShadowTexBuffers(data); updateRenderTargets (data); Int32 shadowTexUnit = (this->getForceTextureUnit() > 0) ? this->getForceTextureUnit() : 7; ShaderProgram *shadowFP = this->getShadowFragmentProgram(); if(shadowFP == NULL) { ShaderProgramUnrecPtr newShadowFP = ShaderProgram::createLocal(); newShadowFP->setShaderType(GL_FRAGMENT_SHADER); newShadowFP->setProgram (_dirFPCode ); newShadowFP->addUniformVariable("SSME_matEyeToLight", matEyeToLight); newShadowFP->addUniformVariable("SSME_matLightProj", matLightProj ); newShadowFP->addUniformVariable("SSME_texShadow", shadowTexUnit); this->setShadowFragmentProgram(newShadowFP); shadowFP = newShadowFP; } else { shadowFP->updateUniformVariable("SSME_matEyeToLight", matEyeToLight); shadowFP->updateUniformVariable("SSME_matLightProj", matLightProj ); } commitChanges(); this->pushPartition(ract); { RenderPartition *part = ract->getActivePartition( ); Window *win = ract->getWindow ( ); FrameBufferObject *target = data->getRenderTargets (0); Background *back = data->getBackground ( ); part->setRenderTarget(target); part->setWindow (win ); part->calcViewportDimension(0.f, 0.f, 1.f, 1.f, target->getWidth (), target->getHeight() ); part->setupProjection(matLightProj, matLightProjTrans); part->setupViewing (matWorldToLight ); part->setNear (parentPart->getNear()); part->setFar (parentPart->getFar ()); part->calcFrustum ( ); part->setBackground (back ); // force material for shadow map generation part->overrideMaterial(data->getLightPassMaterials(0), ract->getActNode ( ) ); this->recurseFrom(ract, dirL); ract->useNodeList(false ); // undo override part->overrideMaterial(NULL, ract->getActNode ( ) ); } this->popPartition(ract); }