Files
ThirdParty-6/ParaView-5.0.1/Examples/Plugins/HiddenLinesRemoval/vtkVisibleLinesPainter.cxx

284 lines
9.0 KiB
C++

/*=========================================================================
Program: Visualization Toolkit
Module: vtkVisibleLinesPainter.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 "vtkVisibleLinesPainter.h"
#include "vtkActor.h"
#include "vtkBoundingBox.h"
#include "vtkPVColorMaterialHelper.h"
#include "vtkFrameBufferObject.h"
#include "vtkPVLightingHelper.h"
#include "vtkShaderProgram2.h"
#include "vtkShader2.h"
#include "vtkShader2Collection.h"
#include "vtkUniformVariables.h"
#include "vtkTextureObject.h"
#include "vtkObjectFactory.h"
#include "vtkPolyData.h"
#include "vtkProperty.h"
#include "vtkRenderer.h"
#include "vtkOpenGLRenderWindow.h"
#include <string>
#include <assert.h>
#include "vtkgl.h"
extern const char* vtkVisibleLinesPainter_vs;
extern const char* vtkVisibleLinesPainter_fs;
vtkStandardNewMacro(vtkVisibleLinesPainter);
#define vtkGetIndex(r,c) (c*4+r)
inline double vtkClamp(double val, const double& min, const double& max)
{
val = (val < min)? min : val;
val = (val > max)? max : val;
return val;
}
class vtkVisibleLinesPainter::vtkInternals
{
public:
vtkWeakPointer<vtkRenderWindow> LastContext;
int LastViewportSize[2];
int ViewportExtent[4];
vtkSmartPointer<vtkFrameBufferObject> FBO;
vtkSmartPointer<vtkTextureObject> DepthImage;
vtkSmartPointer<vtkShaderProgram2> Shader;
vtkSmartPointer<vtkPVLightingHelper> LightingHelper;
vtkSmartPointer<vtkPVColorMaterialHelper> ColorMaterialHelper;
vtkInternals()
{
this->LastViewportSize[0] = this->LastViewportSize[1] = 0;
this->LightingHelper = vtkSmartPointer<vtkPVLightingHelper>::New();
this->ColorMaterialHelper = vtkSmartPointer<vtkPVColorMaterialHelper>::New();
}
void ClearTextures()
{
this->DepthImage = 0;
if (this->FBO)
{
this->FBO->RemoveAllColorBuffers();
this->FBO->RemoveDepthBuffer();
}
}
void ClearGraphicsResources()
{
this->ClearTextures();
this->FBO = 0;
this->DepthImage = 0;
this->LightingHelper->Initialize(0,VTK_SHADER_TYPE_VERTEX);
this->ColorMaterialHelper->Initialize(0);
if(this->Shader!=0)
{
this->Shader->ReleaseGraphicsResources();
this->Shader = 0;
}
}
};
//----------------------------------------------------------------------------
vtkVisibleLinesPainter::vtkVisibleLinesPainter()
{
this->Internals = new vtkInternals();
}
//----------------------------------------------------------------------------
vtkVisibleLinesPainter::~vtkVisibleLinesPainter()
{
this->ReleaseGraphicsResources(this->Internals->LastContext);
delete this->Internals;
}
//----------------------------------------------------------------------------
void vtkVisibleLinesPainter::ReleaseGraphicsResources(vtkWindow* win)
{
this->Internals->ClearGraphicsResources();
this->Internals->LastContext = 0;
this->Superclass::ReleaseGraphicsResources(win);
}
//----------------------------------------------------------------------------
bool vtkVisibleLinesPainter::CanRender(vtkRenderer* vtkNotUsed(renderer),
vtkActor* actor)
{
return (actor->GetProperty()->GetRepresentation() == VTK_WIREFRAME);
}
//----------------------------------------------------------------------------
void vtkVisibleLinesPainter::PrepareForRendering(vtkRenderer* renderer, vtkActor* actor)
{
if (!this->CanRender(renderer, actor))
{
this->Internals->ClearGraphicsResources();
this->Internals->LastContext = 0;
this->Superclass::PrepareForRendering(renderer, actor);
return;
}
vtkRenderWindow* renWin = renderer->GetRenderWindow();
if (this->Internals->LastContext != renWin)
{
this->Internals->ClearGraphicsResources();
}
this->Internals->LastContext = renWin;
int viewsize[2], vieworigin[2];
renderer->GetTiledSizeAndOrigin(&viewsize[0], &viewsize[1], &vieworigin[0], &vieworigin[1]);
if (this->Internals->LastViewportSize[0] != viewsize[0] ||
this->Internals->LastViewportSize[1] != viewsize[1])
{
// View size has changed, we need to re-generate the textures.
this->Internals->ClearTextures();
}
this->Internals->LastViewportSize[0] = viewsize[0];
this->Internals->LastViewportSize[1] = viewsize[1];
if (!this->Internals->FBO)
{
vtkFrameBufferObject* fbo = vtkFrameBufferObject::New();
fbo->SetContext(renWin);
this->Internals->FBO = fbo;
fbo->Delete();
}
if (!this->Internals->DepthImage)
{
vtkTextureObject* depthImage = vtkTextureObject::New();
depthImage->SetContext(renWin);
depthImage->Create2D(viewsize[0], viewsize[1], 1, VTK_VOID, false);
this->Internals->FBO->SetDepthBuffer(depthImage);
this->Internals->DepthImage = depthImage;
depthImage->Delete();
}
if (!this->Internals->Shader)
{
vtkShaderProgram2* pgm = vtkShaderProgram2::New();
pgm->SetContext(static_cast<vtkOpenGLRenderWindow *>(renWin));
vtkShader2 *s1=vtkShader2::New();
s1->SetType(VTK_SHADER_TYPE_VERTEX);
s1->SetSourceCode(vtkVisibleLinesPainter_vs);
s1->SetContext(pgm->GetContext());
vtkShader2 *s2=vtkShader2::New();
s2->SetType(VTK_SHADER_TYPE_FRAGMENT);
s2->SetSourceCode(vtkVisibleLinesPainter_fs);
s2->SetContext(pgm->GetContext());
pgm->GetShaders()->AddItem(s1);
pgm->GetShaders()->AddItem(s2);
s1->Delete();
s2->Delete();
this->Internals->LightingHelper->Initialize(pgm,VTK_SHADER_TYPE_VERTEX);
this->Internals->ColorMaterialHelper->Initialize(pgm);
this->Internals->Shader = pgm;
pgm->Delete();
}
// Now compute the bounds of the pixels that this dataset is going to occupy
// on the screen.
this->Internals->ViewportExtent[0] = vieworigin[0];
this->Internals->ViewportExtent[1] = vieworigin[0] + viewsize[0];
this->Internals->ViewportExtent[2] = vieworigin[1];
this->Internals->ViewportExtent[3] = vieworigin[1] + viewsize[1];
this->Superclass::PrepareForRendering(renderer, actor);
}
//----------------------------------------------------------------------------
void vtkVisibleLinesPainter::RenderInternal(vtkRenderer *renderer,
vtkActor *actor,
unsigned long typeflags,
bool forceCompileOnly)
{
if (!this->CanRender(renderer, actor))
{
this->Superclass::RenderInternal(renderer, actor, typeflags,
forceCompileOnly);
return;
}
vtkRenderWindow* renWin = renderer->GetRenderWindow();
// Save context state to be able to restore.
glPushAttrib(GL_ALL_ATTRIB_BITS);
glDisable(GL_POLYGON_OFFSET_FILL);
glDisable(GL_POLYGON_OFFSET_LINE);
glDisable(GL_POLYGON_OFFSET_POINT);
// we get the view port size (not the renderwindow size).
int viewsize[2], vieworigin[2];
renderer->GetTiledSizeAndOrigin(&viewsize[0], &viewsize[1], &vieworigin[0], &vieworigin[1]);
// Pass One: Render surface, we are only interested in the depth buffer, hence
// we don't clear the color buffer. However, color buffer attachment is needed
// for FBO completeness (verify).
this->Internals->FBO->StartNonOrtho(viewsize[0], viewsize[1], false);
glClear(GL_DEPTH_BUFFER_BIT);
this->Superclass::Superclass::RenderInternal(renderer, actor, typeflags,
forceCompileOnly);
glFlush();
this->Internals->FBO->UnBind();
// Now paste back the rendered image into the default framebuffer.
renWin->MakeCurrent();
this->Internals->LightingHelper->PrepareForRendering();
this->Internals->ColorMaterialHelper->PrepareForRendering();
this->Internals->Shader->Build();
if(this->Internals->Shader->GetLastBuildStatus()
!=VTK_SHADER_PROGRAM2_LINK_SUCCEEDED)
{
vtkErrorMacro("Pass Two failed.");
abort();
}
this->Internals->ColorMaterialHelper->Render();
vtkgl::ActiveTexture(vtkgl::TEXTURE0);
this->Internals->DepthImage->Bind();
int value=0;
this->Internals->Shader->GetUniformVariables()->SetUniformi("texDepth",1,&value);
float fvalues[2];
fvalues[0]=static_cast<float>(viewsize[0]);
fvalues[1]=static_cast<float>(viewsize[1]);
this->Internals->Shader->GetUniformVariables()->SetUniformf("uViewSize",2,fvalues);
this->Internals->Shader->Use();
if(!this->Internals->Shader->IsValid())
{
vtkErrorMacro(<<" validation of the program failed: "<<this->Internals->Shader->GetLastValidateLog());
}
this->Superclass::RenderInternal(renderer, actor, typeflags, forceCompileOnly);
this->Internals->Shader->Restore();
// Pop the attributes.
glPopAttrib();
}
//----------------------------------------------------------------------------
void vtkVisibleLinesPainter::PrintSelf(ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os, indent);
}