You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
734 lines
20 KiB
C++
734 lines
20 KiB
C++
/*=========================================================================
|
|
|
|
Program: Visualization Toolkit
|
|
Module: vtkShadowMapPass.cxx
|
|
|
|
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
|
|
All rights reserved.
|
|
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
|
|
|
|
This software is distributed WITHOUT ANY WARRANTY; without even
|
|
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
|
PURPOSE. See the above copyright notice for more information.
|
|
|
|
=========================================================================*/
|
|
|
|
#include "vtkShadowMapPass.h"
|
|
#include "vtkObjectFactory.h"
|
|
#include <cassert>
|
|
|
|
#include "vtkRenderState.h"
|
|
#include "vtkOpenGLRenderer.h"
|
|
#include "vtkgl.h"
|
|
#include "vtkFrameBufferObject.h"
|
|
#include "vtkTextureObject.h"
|
|
#include "vtkShaderProgram2.h"
|
|
#include "vtkShader2.h"
|
|
#include "vtkShader2Collection.h"
|
|
#include "vtkUniformVariables.h"
|
|
#include "vtkOpenGLRenderWindow.h"
|
|
#include "vtkOpenGLError.h"
|
|
#include "vtkTextureUnitManager.h"
|
|
#include "vtkInformationIntegerKey.h"
|
|
#include "vtkMath.h"
|
|
|
|
// to be able to dump intermediate passes into png files for debugging.
|
|
// only for vtkShadowMapPass developers.
|
|
//#define VTK_SHADOW_MAP_PASS_DEBUG
|
|
//#define DONT_DUPLICATE_LIGHTS
|
|
|
|
#include "vtkPNGWriter.h"
|
|
#include "vtkImageImport.h"
|
|
#include "vtkPixelBufferObject.h"
|
|
#include "vtkImageExtractComponents.h"
|
|
#include "vtkLightCollection.h"
|
|
#include "vtkLight.h"
|
|
#include "vtkInformation.h"
|
|
#include "vtkCamera.h"
|
|
#include "vtkAbstractTransform.h" // for helper classes stack and concatenation
|
|
#include "vtkPerspectiveTransform.h"
|
|
#include "vtkTransform.h"
|
|
|
|
#include <sstream>
|
|
#include "vtkStdString.h"
|
|
|
|
#include "vtkImageShiftScale.h"
|
|
#include "vtkImageExport.h"
|
|
#include "vtkImageData.h"
|
|
#include "vtkImplicitHalo.h"
|
|
#include "vtkSampleFunction.h"
|
|
|
|
#include "vtkImplicitWindowFunction.h"
|
|
#include "vtkImplicitSum.h"
|
|
|
|
// For vtkShadowMapBakerPassTextures, vtkShadowMapBakerPassLightCameras
|
|
#include "vtkShadowMapPassInternal.h"
|
|
#include "vtkShadowMapBakerPass.h"
|
|
#include "vtkMatrixToLinearTransform.h"
|
|
|
|
// debugging
|
|
#include "vtkOpenGLState.h"
|
|
#include "vtkTimerLog.h"
|
|
//#include "vtkBreakPoint.h"
|
|
|
|
vtkStandardNewMacro(vtkShadowMapPass);
|
|
vtkCxxSetObjectMacro(vtkShadowMapPass,ShadowMapBakerPass,
|
|
vtkShadowMapBakerPass);
|
|
vtkCxxSetObjectMacro(vtkShadowMapPass,OpaquePass,
|
|
vtkRenderPass);
|
|
|
|
extern const char *vtkShadowMapPassShader_fs;
|
|
extern const char *vtkShadowMapPassShader_vs;
|
|
extern const char *vtkLighting_s;
|
|
|
|
// ----------------------------------------------------------------------------
|
|
vtkShadowMapPass::vtkShadowMapPass()
|
|
{
|
|
this->ShadowMapBakerPass=0;
|
|
this->OpaquePass=0;
|
|
|
|
this->Program=0;
|
|
|
|
this->IntensityMap=0;
|
|
this->IntensitySource=0;
|
|
this->IntensityExporter=0;
|
|
this->Halo=0;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
vtkShadowMapPass::~vtkShadowMapPass()
|
|
{
|
|
if(this->ShadowMapBakerPass!=0)
|
|
{
|
|
this->ShadowMapBakerPass->Delete();
|
|
}
|
|
if(this->OpaquePass!=0)
|
|
{
|
|
this->OpaquePass->Delete();
|
|
}
|
|
|
|
if(this->Program!=0)
|
|
{
|
|
this->Program->Delete();
|
|
}
|
|
|
|
if(this->IntensityMap!=0)
|
|
{
|
|
vtkErrorMacro(<<"IntensityMap should have been deleted in ReleaseGraphicsResources().");
|
|
}
|
|
|
|
if(this->IntensitySource!=0)
|
|
{
|
|
this->IntensitySource->Delete();
|
|
}
|
|
|
|
if(this->IntensityExporter!=0)
|
|
{
|
|
this->IntensityExporter->Delete();
|
|
}
|
|
|
|
if(this->Halo!=0)
|
|
{
|
|
this->Halo->Delete();
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
void vtkShadowMapPass::PrintSelf(ostream& os, vtkIndent indent)
|
|
{
|
|
this->Superclass::PrintSelf(os,indent);
|
|
|
|
os << indent << "ShadowMapBackerPass: ";
|
|
if(this->ShadowMapBakerPass!=0)
|
|
{
|
|
this->ShadowMapBakerPass->PrintSelf(os,indent);
|
|
}
|
|
else
|
|
{
|
|
os << "(none)" <<endl;
|
|
}
|
|
os << indent << "OpaquePass: ";
|
|
if(this->OpaquePass!=0)
|
|
{
|
|
this->OpaquePass->PrintSelf(os,indent);
|
|
}
|
|
else
|
|
{
|
|
os << "(none)" <<endl;
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// Description:
|
|
// Perform rendering according to a render state \p s.
|
|
// \pre s_exists: s!=0
|
|
void vtkShadowMapPass::Render(const vtkRenderState *s)
|
|
{
|
|
assert("pre: s_exists" && s!=0);
|
|
|
|
vtkOpenGLClearErrorMacro();
|
|
|
|
this->NumberOfRenderedProps=0;
|
|
|
|
vtkOpenGLRenderer *r=static_cast<vtkOpenGLRenderer *>(s->GetRenderer());
|
|
vtkOpenGLRenderWindow *context=static_cast<vtkOpenGLRenderWindow *>(
|
|
r->GetRenderWindow());
|
|
#ifdef VTK_SHADOW_MAP_PASS_DEBUG
|
|
vtkOpenGLState *state=new vtkOpenGLState(context);
|
|
#endif
|
|
|
|
if(this->ShadowMapBakerPass!=0 &&
|
|
// this->ShadowMapBakerPass->GetOpaquePass()!=0
|
|
this->OpaquePass!=0)
|
|
{
|
|
// Test for Hardware support. If not supported, just render the delegate.
|
|
bool supported=vtkFrameBufferObject::IsSupported(r->GetRenderWindow());
|
|
|
|
if(!supported)
|
|
{
|
|
vtkErrorMacro("FBOs are not supported by the context. Cannot use shadow mapping.");
|
|
}
|
|
if(supported)
|
|
{
|
|
supported=vtkTextureObject::IsSupported(r->GetRenderWindow());
|
|
if(!supported)
|
|
{
|
|
vtkErrorMacro("Texture Objects are not supported by the context. Cannot use shadow mapping.");
|
|
}
|
|
}
|
|
|
|
if(supported)
|
|
{
|
|
supported=
|
|
vtkShaderProgram2::IsSupported(static_cast<vtkOpenGLRenderWindow *>(
|
|
r->GetRenderWindow()));
|
|
if(!supported)
|
|
{
|
|
vtkErrorMacro("GLSL is not supported by the context. Cannot use shadow mapping.");
|
|
}
|
|
}
|
|
|
|
if(!supported)
|
|
{
|
|
this->OpaquePass->Render(s);
|
|
this->NumberOfRenderedProps+=
|
|
this->OpaquePass->GetNumberOfRenderedProps();
|
|
return;
|
|
}
|
|
|
|
if(!this->ShadowMapBakerPass->GetHasShadows())
|
|
{
|
|
this->OpaquePass->Render(s);
|
|
this->NumberOfRenderedProps+=
|
|
this->OpaquePass->GetNumberOfRenderedProps();
|
|
return;
|
|
}
|
|
|
|
// Copy the list of lights and the lights. We cannot just modify them in
|
|
// place because it will change their modification time.
|
|
// Modification time is used directly (or indirectly if there is some
|
|
// light actors) to avoid rebuilding the shadow maps.
|
|
|
|
vtkLightCollection *lights=r->GetLights();
|
|
|
|
vtkLightCollection *lights2;
|
|
#ifdef DONT_DUPLICATE_LIGHTS
|
|
if(this->CompositeZPass==0)
|
|
{
|
|
#endif
|
|
// parallel rendering hangs with this technique
|
|
lights2=vtkLightCollection::New();
|
|
lights->InitTraversal();
|
|
vtkLight *l=lights->GetNextItem();
|
|
size_t lightIndex=0;
|
|
while(l!=0)
|
|
{
|
|
vtkLight *l2=l->ShallowClone();
|
|
lights2->AddItem(l2);
|
|
l2->Delete();
|
|
l=lights->GetNextItem();
|
|
++lightIndex;
|
|
}
|
|
|
|
// save the original light collection.
|
|
lights->Register(this);
|
|
// make the copy the current light collection on the renderer
|
|
r->SetLightCollection(lights2);
|
|
#ifdef DONT_DUPLICATE_LIGHTS
|
|
}
|
|
else
|
|
{
|
|
// safe and slow for parallel rendering
|
|
lights2=lights;
|
|
}
|
|
#endif
|
|
|
|
// Render scene with shadowing lights off.
|
|
// depth writing and testing on.
|
|
|
|
// save the lights switches.
|
|
bool *lightSwitches=new bool[lights2->GetNumberOfItems()];
|
|
|
|
lights2->InitTraversal();
|
|
l=lights2->GetNextItem();
|
|
lightIndex=0;
|
|
while(l!=0)
|
|
{
|
|
lightSwitches[lightIndex]=l->GetSwitch()==1;
|
|
l=lights2->GetNextItem();
|
|
++lightIndex;
|
|
}
|
|
|
|
bool autoLight=r->GetAutomaticLightCreation()==1;
|
|
r->SetAutomaticLightCreation(false);
|
|
|
|
// switch the shadowing lights off.
|
|
lights2->InitTraversal();
|
|
l=lights2->GetNextItem();
|
|
lightIndex=0;
|
|
while(l!=0)
|
|
{
|
|
if(lightSwitches[lightIndex] &&
|
|
this->ShadowMapBakerPass->LightCreatesShadow(l))
|
|
{
|
|
l->SetSwitch(false);
|
|
}
|
|
l=lights2->GetNextItem();
|
|
++lightIndex;
|
|
}
|
|
|
|
#ifdef VTK_SHADOW_MAP_PASS_DEBUG
|
|
cout << "finish before rendering geometry without shadowing lights" << endl;
|
|
glFinish();
|
|
#endif
|
|
|
|
// render for real for non shadowing lights.
|
|
// note this time we use the list of props after culling.
|
|
this->OpaquePass->Render(s);
|
|
this->NumberOfRenderedProps+=
|
|
this->OpaquePass->GetNumberOfRenderedProps();
|
|
|
|
#ifdef VTK_SHADOW_MAP_PASS_DEBUG
|
|
cout << "finish after rendering geometry without shadowing lights" << endl;
|
|
glFinish();
|
|
#endif
|
|
|
|
// now disable depth writing,
|
|
// For each shadowing light,
|
|
//
|
|
glDepthMask(GL_FALSE);
|
|
|
|
// maybe ivar:
|
|
if(this->Program==0)
|
|
{
|
|
this->Program=vtkShaderProgram2::New();
|
|
}
|
|
this->Program->SetContext(context);
|
|
vtkShader2Collection *shaders=this->Program->GetShaders();
|
|
|
|
if(this->ShadowMapBakerPass->GetNeedUpdate())
|
|
{
|
|
this->ShadowMapBakerPass->SetUpToDate();
|
|
// we have to perform a concatenation. remove all the shaders first.
|
|
this->Program->ReleaseGraphicsResources();
|
|
shaders->RemoveAllItems();
|
|
size_t nbLights=
|
|
this->ShadowMapBakerPass->GetShadowMaps()->Vector.size();
|
|
std::ostringstream ostVS;
|
|
|
|
std::ostringstream numLights;
|
|
numLights << endl << "#define VTK_LIGHTING_NUMBER_OF_LIGHTS " << nbLights << endl;
|
|
|
|
vtkStdString vertShader(vtkShadowMapPassShader_vs);
|
|
size_t version_loc = vertShader.find("#version 110");
|
|
|
|
vertShader.insert(version_loc + 13, numLights.str());
|
|
|
|
ostVS << vertShader;
|
|
|
|
vtkStdString *vsCode=new vtkStdString;
|
|
(*vsCode)=ostVS.str();
|
|
|
|
std::ostringstream ostLightingVS;
|
|
|
|
vtkStdString lightShader(vtkLighting_s);
|
|
version_loc = lightShader.find("#version 110");
|
|
|
|
lightShader.insert(version_loc + 13, numLights.str());
|
|
|
|
ostLightingVS << lightShader;
|
|
|
|
vtkStdString *lightingVsCode=new vtkStdString;
|
|
(*lightingVsCode)=ostLightingVS.str();
|
|
|
|
|
|
std::ostringstream ostFS;
|
|
|
|
vtkStdString fragShader(vtkShadowMapPassShader_fs);
|
|
version_loc = fragShader.find("#version 110");
|
|
|
|
fragShader.insert(version_loc + 13, numLights.str());
|
|
|
|
ostFS << fragShader;
|
|
|
|
vtkStdString *fsCode=new vtkStdString;
|
|
(*fsCode)=ostFS.str();
|
|
|
|
|
|
|
|
vtkShader2 *vs=vtkShader2::New();
|
|
vs->SetContext(context);
|
|
vs->SetType(VTK_SHADER_TYPE_VERTEX);
|
|
vs->SetSourceCode(vsCode->c_str());
|
|
delete vsCode;
|
|
shaders->AddItem(vs);
|
|
vs->Delete();
|
|
|
|
vtkShader2 *lightingVS=vtkShader2::New();
|
|
lightingVS->SetContext(context);
|
|
lightingVS->SetType(VTK_SHADER_TYPE_VERTEX);
|
|
lightingVS->SetSourceCode(lightingVsCode->c_str());
|
|
delete lightingVsCode;
|
|
shaders->AddItem(lightingVS);
|
|
lightingVS->Delete();
|
|
|
|
vtkShader2 *fs=vtkShader2::New();
|
|
fs->SetContext(context);
|
|
fs->SetType(VTK_SHADER_TYPE_FRAGMENT);
|
|
fs->SetSourceCode(fsCode->c_str());
|
|
delete fsCode;
|
|
shaders->AddItem(fs);
|
|
fs->Delete();
|
|
}
|
|
|
|
#ifdef VTK_SHADOW_MAP_PASS_DEBUG
|
|
this->Program->Build();
|
|
|
|
if(this->Program->GetLastBuildStatus()!=VTK_SHADER_PROGRAM2_LINK_SUCCEEDED)
|
|
{
|
|
vtkErrorMacro("Couldn't build the shader program. At this point , it can be an error in a shader or a driver bug.");
|
|
delete[] lightSwitches;
|
|
return;
|
|
}
|
|
|
|
this->Program->PrintActiveUniformVariablesOnCout();
|
|
#endif
|
|
|
|
r->SetShaderProgram(this->Program);
|
|
|
|
if(this->IntensityMap==0)
|
|
{
|
|
this->IntensityMap=vtkTextureObject::New();
|
|
this->IntensityMap->SetContext(context);
|
|
this->IntensityMap->SetWrapS(vtkTextureObject::Clamp);
|
|
this->IntensityMap->SetWrapT(vtkTextureObject::Clamp);
|
|
this->IntensityMap->SetMinificationFilter(vtkTextureObject::Linear);
|
|
this->IntensityMap->SetLinearMagnification(true);
|
|
}
|
|
if(this->IntensityMap->GetWidth()!=
|
|
this->ShadowMapBakerPass->GetResolution())
|
|
{
|
|
// Load the spotlight intensity map.
|
|
vtkPixelBufferObject *pbo=vtkPixelBufferObject::New();
|
|
pbo->SetContext(context);
|
|
this->BuildSpotLightIntensityMap();
|
|
this->IntensityExporter->Update();
|
|
|
|
#ifdef VTK_SHADOW_MAP_PASS_DEBUG
|
|
vtkPNGWriter *writer=vtkPNGWriter::New();
|
|
writer->SetFileName("IntensityMap.png");
|
|
writer->SetInput(this->IntensityExporter->GetInput());
|
|
writer->Write();
|
|
writer->Delete();
|
|
#endif
|
|
unsigned char *rawPointer=
|
|
static_cast<unsigned char*>(
|
|
this->IntensityExporter->GetPointerToData());
|
|
|
|
vtkIdType continuousInc[3];
|
|
vtkImageData *im=this->IntensityExporter->GetInput();
|
|
im->GetContinuousIncrements(im->GetExtent(),continuousInc[0],
|
|
continuousInc[1],continuousInc[2]);
|
|
|
|
unsigned int dims[2];
|
|
dims[0]=this->ShadowMapBakerPass->GetResolution();
|
|
dims[1]=dims[0];
|
|
pbo->Upload2D(VTK_UNSIGNED_CHAR,rawPointer,dims,1,continuousInc);
|
|
|
|
this->IntensityMap->Create2D(this->ShadowMapBakerPass->GetResolution(),
|
|
this->ShadowMapBakerPass->GetResolution(),
|
|
1,pbo,false);
|
|
pbo->Delete();
|
|
}
|
|
|
|
// set uniforms
|
|
// set TO,TU
|
|
|
|
vtkUniformVariables *u=this->Program->GetUniformVariables();
|
|
|
|
vtkMatrix4x4 *tmp=vtkMatrix4x4::New();
|
|
|
|
// WE CANNOT USE THIS WITH Ice-T
|
|
// vtkLinearTransform *viewCamera_Inv=r->GetActiveCamera()
|
|
// ->GetViewTransformObject()->GetLinearInverse();
|
|
// vtkBreakPoint::Break();
|
|
// REQUIRED with Ice-T
|
|
// We assume that at this point of the execution
|
|
// modelview matrix is actually on the view matrix, that is
|
|
// model matrix is identity.
|
|
|
|
GLfloat m[16];
|
|
glGetFloatv(GL_MODELVIEW_MATRIX,m);
|
|
vtkMatrix4x4 *mat=vtkMatrix4x4::New();
|
|
int row=0;
|
|
while(row<4)
|
|
{
|
|
int column=0;
|
|
while(column<4)
|
|
{
|
|
mat->SetElement(row,column,static_cast<double>(m[column*4+row]));
|
|
++column;
|
|
}
|
|
++row;
|
|
}
|
|
mat->Invert();
|
|
vtkMatrixToLinearTransform *viewCamera_Inv
|
|
=vtkMatrixToLinearTransform::New();
|
|
viewCamera_Inv->SetInput(mat);
|
|
mat->Delete();
|
|
|
|
vtkPerspectiveTransform *transform=vtkPerspectiveTransform::New();
|
|
|
|
// identity. pre-multiply mode
|
|
|
|
transform->Translate(0.5,0.5,0.5); // bias
|
|
transform->Scale(0.5,0.5,0.5); // scale
|
|
|
|
|
|
// switch the shadowing lights on.
|
|
lights2->InitTraversal();
|
|
l=lights2->GetNextItem();
|
|
lightIndex=0;
|
|
int shadowingLightIndex=0;
|
|
|
|
GLint savedMatrixMode;
|
|
glGetIntegerv(GL_MATRIX_MODE,&savedMatrixMode);
|
|
|
|
while(l!=0)
|
|
{
|
|
if(lightSwitches[lightIndex] &&
|
|
this->ShadowMapBakerPass->LightCreatesShadow(l) )
|
|
{
|
|
l->SetSwitch(true);
|
|
|
|
// setup texture matrix.
|
|
glMatrixMode(GL_TEXTURE);
|
|
vtkgl::ActiveTexture(vtkgl::TEXTURE0+
|
|
static_cast<GLenum>(shadowingLightIndex));
|
|
glPushMatrix();
|
|
// scale_bias*projection_light[i]*view_light[i]*view_camera_inv
|
|
|
|
vtkCamera *lightCamera=
|
|
this->ShadowMapBakerPass->GetLightCameras()->Vector[
|
|
static_cast<size_t>(shadowingLightIndex)];
|
|
transform->Push();
|
|
transform->Concatenate(
|
|
lightCamera->GetProjectionTransformObject(1,-1,1));
|
|
transform->Concatenate(lightCamera->GetViewTransformObject());
|
|
transform->Concatenate(viewCamera_Inv);
|
|
transform->GetMatrix(tmp);
|
|
transform->Pop();
|
|
tmp->Transpose();
|
|
glLoadMatrixd(tmp->Element[0]);
|
|
|
|
// setup shadowMap texture object and texture unit
|
|
vtkTextureObject *map=
|
|
this->ShadowMapBakerPass->GetShadowMaps()->Vector[
|
|
static_cast<size_t>(shadowingLightIndex)];
|
|
map->SetDepthTextureCompare(true);
|
|
map->SetLinearMagnification(true);
|
|
map->SetMinificationFilter(vtkTextureObject::Linear);
|
|
map->Bind();
|
|
|
|
std::ostringstream ostShadowMapTextureUnit;
|
|
ostShadowMapTextureUnit << "shadowMaps[" << shadowingLightIndex << "]";
|
|
|
|
vtkStdString *shadowMapTextureUnitString=new vtkStdString;
|
|
(*shadowMapTextureUnitString)=ostShadowMapTextureUnit.str();
|
|
|
|
u->SetUniformi(shadowMapTextureUnitString->c_str(),1,
|
|
&shadowingLightIndex);
|
|
|
|
delete shadowMapTextureUnitString;
|
|
|
|
++shadowingLightIndex;
|
|
}
|
|
else
|
|
{
|
|
l->SetSwitch(false); // any other light
|
|
}
|
|
l=lights2->GetNextItem();
|
|
++lightIndex;
|
|
}
|
|
|
|
// Ice-T
|
|
viewCamera_Inv->Delete();
|
|
|
|
vtkgl::ActiveTexture(vtkgl::TEXTURE0+
|
|
static_cast<GLenum>(shadowingLightIndex));
|
|
this->IntensityMap->Bind();
|
|
u->SetUniformi("spotLightShape",1,&shadowingLightIndex);
|
|
|
|
// DO not delete iewCamera_Inv, this is an internal ivar of vtkTransform.
|
|
transform->Delete();
|
|
tmp->Delete();
|
|
|
|
#ifdef VTK_SHADOW_MAP_PASS_DEBUG
|
|
cout << "finish before rendering geometry with shadowing lights" << endl;
|
|
glFinish();
|
|
#endif
|
|
|
|
vtkRenderState s2(r);
|
|
s2.SetFrameBuffer(s->GetFrameBuffer());
|
|
vtkInformation *requiredKeys=vtkInformation::New();
|
|
requiredKeys->Set(vtkShadowMapBakerPass::RECEIVER(),0);
|
|
s2.SetRequiredKeys(requiredKeys);
|
|
s2.SetPropArrayAndCount(s->GetPropArray(),s->GetPropArrayCount());
|
|
|
|
// Blend the result with the exising scene
|
|
glAlphaFunc(GL_GREATER,0.9f);
|
|
glEnable(GL_ALPHA_TEST);
|
|
// render scene
|
|
|
|
bool rendererEraseFlag=r->GetErase()==1;
|
|
r->SetErase(0);
|
|
|
|
glMatrixMode(savedMatrixMode);
|
|
|
|
this->OpaquePass->Render(&s2);
|
|
this->NumberOfRenderedProps+=
|
|
this->OpaquePass->GetNumberOfRenderedProps();
|
|
|
|
requiredKeys->Delete();
|
|
|
|
r->SetErase(rendererEraseFlag);
|
|
glDisable(GL_ALPHA_TEST);
|
|
|
|
#ifdef VTK_SHADOW_MAP_PASS_DEBUG
|
|
cout << "finish after rendering geometry with shadowing lights" << endl;
|
|
glFinish();
|
|
#endif
|
|
|
|
// restore texture matrices
|
|
int i=0;
|
|
glMatrixMode(GL_TEXTURE);
|
|
while(i<shadowingLightIndex)
|
|
{
|
|
vtkgl::ActiveTexture(vtkgl::TEXTURE0+
|
|
static_cast<GLenum>(i));
|
|
glPopMatrix();
|
|
++i;
|
|
}
|
|
vtkgl::ActiveTexture(vtkgl::TEXTURE0);
|
|
|
|
r->SetShaderProgram(0);
|
|
|
|
glMatrixMode(savedMatrixMode);
|
|
|
|
#ifdef DONT_DUPLICATE_LIGHTS
|
|
if(this->CompositeZPass==0)
|
|
{
|
|
#endif
|
|
// restore original light collection
|
|
r->SetLightCollection(lights);
|
|
lights->Delete();
|
|
lights2->Delete();
|
|
#ifdef DONT_DUPLICATE_LIGHTS
|
|
}
|
|
else
|
|
{
|
|
// restore original light switchs.
|
|
lights->InitTraversal();
|
|
l=lights->GetNextItem();
|
|
lightIndex=0;
|
|
while(l!=0)
|
|
{
|
|
l->SetSwitch(lightSwitches[lightIndex]);
|
|
l=lights->GetNextItem();
|
|
++lightIndex;
|
|
}
|
|
}
|
|
#endif
|
|
delete[] lightSwitches;
|
|
|
|
r->SetAutomaticLightCreation(autoLight);
|
|
glDepthMask(GL_TRUE);
|
|
|
|
}
|
|
else
|
|
{
|
|
vtkWarningMacro(<<" no ShadowMapBakerPass or no OpaquePass on the ShadowMapBakerPass.");
|
|
}
|
|
|
|
vtkOpenGLCheckErrorMacro("failed after Render");
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
void vtkShadowMapPass::BuildSpotLightIntensityMap()
|
|
{
|
|
if(this->IntensitySource==0)
|
|
{
|
|
this->IntensitySource=vtkSampleFunction::New();
|
|
this->IntensityExporter=vtkImageExport::New();
|
|
this->Halo=vtkImplicitHalo::New();
|
|
|
|
vtkImplicitSum *scale=vtkImplicitSum::New();
|
|
scale->AddFunction(this->Halo,255.0);
|
|
scale->SetNormalizeByWeight(false);
|
|
this->IntensitySource->SetImplicitFunction(scale);
|
|
scale->Delete();
|
|
}
|
|
unsigned int resolution=this->ShadowMapBakerPass->GetResolution();
|
|
|
|
this->Halo->SetRadius(resolution/2.0);
|
|
this->Halo->SetCenter(resolution/2.0,
|
|
resolution/2.0,0.0);
|
|
this->Halo->SetFadeOut(0.1);
|
|
|
|
this->IntensitySource->SetOutputScalarType(VTK_UNSIGNED_CHAR);
|
|
this->IntensitySource->SetSampleDimensions(
|
|
static_cast<int>(resolution),
|
|
static_cast<int>(resolution),1);
|
|
this->IntensitySource->SetModelBounds(0.0,resolution-1.0,
|
|
0.0,resolution-1.0,
|
|
0.0,0.0);
|
|
this->IntensitySource->SetComputeNormals(false);
|
|
|
|
this->IntensityExporter->SetInputConnection(
|
|
this->IntensitySource->GetOutputPort());
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// Description:
|
|
// Release graphics resources and ask components to release their own
|
|
// resources.
|
|
// \pre w_exists: w!=0
|
|
void vtkShadowMapPass::ReleaseGraphicsResources(vtkWindow *w)
|
|
{
|
|
assert("pre: w_exists" && w!=0);
|
|
if(this->ShadowMapBakerPass!=0)
|
|
{
|
|
this->ShadowMapBakerPass->ReleaseGraphicsResources(w);
|
|
}
|
|
if(this->Program!=0)
|
|
{
|
|
this->Program->ReleaseGraphicsResources();
|
|
}
|
|
|
|
if(this->IntensityMap!=0)
|
|
{
|
|
this->IntensityMap->Delete();
|
|
this->IntensityMap=0;
|
|
}
|
|
}
|