Commit 0983eaba authored by Alvaro Sanchez's avatar Alvaro Sanchez

Added vtkValuePass::FLOATING_POINT for point data.

A field array of point data is uploaded as a vertex attribute and rendered to a
float FBO member of the vtkValuePass. The legacy value rendering mode is still
supported as INVERTIBLE_LUT.
parent c37ed290
......@@ -12,6 +12,7 @@ if(VTK_RENDERING_BACKEND STREQUAL "OpenGL2")
TestTranslucentLUTAlphaBlending.cxx
TestTranslucentLUTTextureAlphaBlending.cxx
TestAreaSelections.cxx
TestValuePassFloatingPoint.cxx
)
else()
set(extra_opengl2_tests
......
/*=========================================================================
Program: Visualization Toolkit
Module: TestValuePassFloatingPoint.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.
=========================================================================*/
// Description:
// Tests vtkValuePass in FLOATING_POINT mode. The test generates a 3-component
// float array ("elevationVector") using the loaded polygonal data. Polygons
// are rendered with the ValuePass to its internal floating point frame-buffer.
// The rendered float image is then queried from the vtkValuePass and used to
// generate a color image using vtkLookupTable, the color image is rendered with
// an image actor on-screen. This is repeated for each component.
#include "vtkRegressionTestImage.h"
#include "vtkTestUtilities.h"
#include "vtkActor.h"
#include "vtkCameraPass.h"
#include "vtkCellArray.h"
#include "vtkElevationFilter.h"
#include "vtkInformation.h"
#include "vtkOpenGLRenderer.h"
#include "vtkPLYReader.h"
#include "vtkPointData.h"
#include "vtkPointDataToCellData.h"
#include "vtkPolyData.h"
#include "vtkPolyDataMapper.h"
#include "vtkOpenGLPolyDataMapper.h"
#include "vtkRenderPassCollection.h"
#include "vtkRenderWindow.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkSequencePass.h"
#include "vtkSmartPointer.h"
#include "vtkValuePass.h"
#include "vtkCamera.h"
#include "vtkInteractorStyleTrackballCamera.h"
#include "vtkAbstractMapper.h"
#include "vtkXMLPolyDataReader.h"
#include "vtkFloatArray.h"
#include "vtkLookupTable.h"
#include "vtkColorSeries.h"
#include "vtkImageData.h"
#include "vtkImageActor.h"
#include "vtkImageMapper3D.h"
#include "vtkArrayCalculator.h"
void GenerateElevationArray(vtkSmartPointer<vtkPLYReader> reader)
{
vtkPolyData* data = reader->GetOutput();
double* bounds = data->GetBounds();
vtkSmartPointer<vtkElevationFilter> elevation =
vtkSmartPointer<vtkElevationFilter>::New();
elevation->SetInputConnection(reader->GetOutputPort());
/// Use vtkElevation to generate an array per component. vtkElevation generates
/// a projected distance from each point in the dataset to the line, with respect to
/// the LowPoint ([0, 1] in this case. This is different from having the actual
/// coordinates of a given point.
for (int c = 0; c < 3; c++)
{
std::string name;
switch (c)
{
case 0:
name = "delta_x";
elevation->SetLowPoint(bounds[0], 0.0, 0.0);
elevation->SetHighPoint(bounds[1], 0.0, 0.0);
break;
case 1:
name = "delta_y";
elevation->SetLowPoint(0.0, bounds[2], 0.0);
elevation->SetHighPoint(0.0, bounds[3], 0.0);
break;
case 2:
name = "delta_z";
elevation->SetLowPoint(0.0, 0.0, bounds[4]);
elevation->SetHighPoint(0.0, 0.0, bounds[5]);
break;
}
elevation->Update();
vtkPolyData* result = vtkPolyData::SafeDownCast(elevation->GetOutput());
int outCellFlag;
/// Enums defined in vtkAbstractMapper
vtkDataArray* elevArray = vtkAbstractMapper::GetScalars(result,
VTK_SCALAR_MODE_USE_POINT_FIELD_DATA, VTK_GET_ARRAY_BY_NAME/*acc mode*/,
0/*arr id*/, "Elevation"/*arr name*/, outCellFlag);
if (!elevArray)
{
std::cout << "->> Error: could not find array!" << std::endl;
return;
}
elevArray->SetName(name.c_str());
data->GetPointData()->AddArray(elevArray);
}
/// Generate a 3-component vector array using the single components
/// form elevation.
vtkSmartPointer<vtkArrayCalculator> calc = vtkSmartPointer<vtkArrayCalculator>::New();
calc->SetInputConnection(reader->GetOutputPort());
calc->SetAttributeModeToUsePointData();
calc->AddScalarArrayName("delta_x");
calc->AddScalarArrayName("delta_y");
calc->AddScalarArrayName("delta_z");
calc->SetFunction("delta_x * iHat + delta_y * jHat + delta_z * kHat");
calc->SetResultArrayName("elevationVector");
calc->Update();
vtkPolyData* result = vtkPolyData::SafeDownCast(calc->GetOutput());
int outCellFlag;
vtkDataArray* coordArray = vtkAbstractMapper::GetScalars(result,
VTK_SCALAR_MODE_USE_POINT_FIELD_DATA, VTK_GET_ARRAY_BY_NAME/*acc mode*/,
0/*arr id*/, "elevationVector", outCellFlag);
if (!coordArray)
{
std::cout << "->> Error: could not find array!" << std::endl;
return;
}
/// Include the elevation vector in the original data
data->GetPointData()->AddArray(coordArray);
}
///////////////////////////////////////////////////////////////////////////////
int TestValuePassFloatingPoint(int argc, char *argv[])
{
// Load data
const char *fileName =
vtkTestUtilities::ExpandDataFileName(argc, argv, "Data/dragon.ply");
vtkSmartPointer<vtkPLYReader> reader =
vtkSmartPointer<vtkPLYReader>::New();
reader->SetFileName(fileName);
reader->Update();
// Prepare a 3-component array (data will be appended to reader's output)
GenerateElevationArray(reader);
vtkSmartPointer<vtkPolyDataMapper> mapper =
vtkSmartPointer<vtkPolyDataMapper>::New();
mapper->SetInputConnection(reader->GetOutputPort());
mapper->ScalarVisibilityOn();
vtkSmartPointer<vtkActor> actor =
vtkSmartPointer<vtkActor>::New();
actor->SetMapper(mapper);
// Setup rendering and interaction
vtkSmartPointer<vtkRenderWindowInteractor> interactor =
vtkSmartPointer<vtkRenderWindowInteractor>::New();
vtkSmartPointer<vtkInteractorStyleTrackballCamera> style =
vtkSmartPointer<vtkInteractorStyleTrackballCamera>::New();
interactor->SetInteractorStyle(style);
vtkSmartPointer<vtkRenderWindow> window =
vtkSmartPointer<vtkRenderWindow>::New();
window->SetSize(320, 320);
vtkSmartPointer<vtkRenderer> renderer =
vtkSmartPointer<vtkRenderer>::New();
window->AddRenderer(renderer);
interactor->SetRenderWindow(window);
renderer->AddActor(actor);
renderer->SetBackground(0.2, 0.2, 0.5);
// Setup the value pass
//int const RenderingMode = vtkValuePass::INVERTIBLE_LUT;
int const RenderingMode = vtkValuePass::FLOATING_POINT;
int const comp = 0;
vtkSmartPointer<vtkValuePass> valuePass =
vtkSmartPointer<vtkValuePass>::New();
valuePass->SetRenderingMode(RenderingMode);
valuePass->SetInputComponentToProcess(comp);
//valuePass->SetScalarRange(bounds[0], bounds[1]); /*use the full range*/
valuePass->SetInputArrayToProcess(VTK_SCALAR_MODE_USE_POINT_FIELD_DATA,
"elevationVector");
// 3. Add it to a sequence of passes
vtkSmartPointer<vtkRenderPassCollection> passes =
vtkSmartPointer<vtkRenderPassCollection>::New();
passes->AddItem(valuePass);
vtkSmartPointer<vtkSequencePass> sequence =
vtkSmartPointer<vtkSequencePass>::New();
sequence->SetPasses(passes);
vtkSmartPointer<vtkCameraPass> cameraPass =
vtkSmartPointer<vtkCameraPass>::New();
cameraPass->SetDelegatePass(sequence);
vtkOpenGLRenderer *glRenderer =
vtkOpenGLRenderer::SafeDownCast(renderer.GetPointer());
// Render the value pass
glRenderer->SetPass(cameraPass);
window->Render();
if (RenderingMode == vtkValuePass::FLOATING_POINT)
{
/// Prepare a lut to map the floating point values
vtkSmartPointer<vtkLookupTable> lut = vtkSmartPointer<vtkLookupTable>::New();
lut->SetAlpha(1.0);
//lut->SetRange(elevRange[0], elevRange[1]); /*use the full range*/
vtkSmartPointer<vtkColorSeries> series = vtkSmartPointer<vtkColorSeries>::New();
series->SetColorScheme(vtkColorSeries::WARM);
//series->SetColorScheme(vtkColorSeries::BREWER_DIVERGING_SPECTRAL_11);
series->BuildLookupTable(lut, vtkColorSeries::ORDINAL);
/// Render each component in a separate image
std::vector<vtkSmartPointer<vtkImageData> > colorImages;
for(int c = 0; c < 3; c++)
{
valuePass->SetInputComponentToProcess(c);
window->Render();
/// Get the result.
vtkFloatArray* result = valuePass->GetFloatImageData(renderer);
std::vector<int> ext = valuePass->GetFloatImageExtents(renderer);
/// Map the resulting float image to a color table
vtkUnsignedCharArray* colored = lut->MapScalars(result, VTK_COLOR_MODE_DEFAULT,
0/* single comp*/);
/// Create an image dataset to render in a quad.
vtkSmartPointer<vtkImageData> colorIm = vtkSmartPointer<vtkImageData>::New();
colorIm->SetExtent(&(ext.front()));
colorIm->GetPointData()->SetScalars(colored);
colorImages.push_back(colorIm);
}
// Render the image on-screen
renderer->RemoveActor(actor);
vtkSmartPointer<vtkImageActor> ia_x = vtkSmartPointer<vtkImageActor>::New();
ia_x->GetMapper()->SetInputData(colorImages.at(0));
renderer->AddActor(ia_x);
vtkSmartPointer<vtkImageActor> ia_y = vtkSmartPointer<vtkImageActor>::New();
ia_y->RotateX(90);
ia_y->GetMapper()->SetInputData(colorImages.at(1));
renderer->AddActor(ia_y);
vtkSmartPointer<vtkImageActor> ia_z = vtkSmartPointer<vtkImageActor>::New();
ia_z->RotateY(-90);
ia_z->GetMapper()->SetInputData(colorImages.at(2));
renderer->AddActor(ia_z);
vtkCamera* cam = renderer->GetActiveCamera();
cam->SetPosition(2, 2, 2);
cam->SetFocalPoint(0, 0, 1);
renderer->ResetCamera();
// Use the default pass to render the colored image.
glRenderer->SetPass(NULL);
window->Render();
}
// initialize render loop
int retVal = vtkRegressionTestImage(window.GetPointer());
if( retVal == vtkRegressionTester::DO_INTERACTOR)
{
interactor->Start();
}
return !retVal;
}
......@@ -6,6 +6,7 @@ vtk_module(vtkRenderingCore
vtkIOLegacy
vtkIOParallel
vtkIOXML
vtkIOPLY
vtkTestingCore
vtkTestingRendering
vtkRendering${VTK_RENDERING_BACKEND}
......@@ -32,4 +33,4 @@ vtk_module(vtkRenderingCore
vtkFiltersGeometry
vtkFiltersSources
vtksys
)
\ No newline at end of file
)
......@@ -77,6 +77,7 @@ set(Module_SRCS
vtkTransformFeedback.cxx
vtkTranslucentPass.cxx
vtkValuePass.cxx
vtkValuePassHelper.cxx
vtkVolumetricPass.cxx
)
......@@ -123,6 +124,7 @@ set_source_files_properties(
vtkTextureObject
vtkTextureUnitManager
vtkTransformFeedback
vtkValuePassHelper
WRAP_EXCLUDE)
set_source_files_properties(
......
......@@ -51,6 +51,9 @@ uniform int PrimitiveIDOffset;
// handle coincident offsets
//VTK::Coincident::Dec
// Value raster
//VTK::ValuePass::Dec
void main()
{
// VC position of this fragment. This should not branch/return/discard.
......
......@@ -41,6 +41,9 @@ attribute vec4 vertexMC;
// Apple Bug
//VTK::PrimID::Dec
// Value raster
//VTK::ValuePass::Dec
void main()
{
//VTK::Color::Impl
......@@ -55,5 +58,7 @@ void main()
//VTK::PositionVC::Impl
//VTK::ValuePass::Impl
//VTK::Light::Impl
}
......@@ -51,7 +51,7 @@
#include "vtkTransform.h"
#include "vtkUnsignedIntArray.h"
#include "vtkValuePass.h"
#include "vtkValuePassHelper.h"
#include "vtkShadowMapPass.h"
// Bring in our fragment lit shader symbols.
......@@ -115,6 +115,7 @@ vtkOpenGLPolyDataMapper::vtkOpenGLPolyDataMapper()
this->TimerQuery = 0;
this->ResourceCallback = new vtkOpenGLResourceFreeCallback<vtkOpenGLPolyDataMapper>(this,
&vtkOpenGLPolyDataMapper::ReleaseGraphicsResources);
this->ValuePassHelper = vtkSmartPointer<vtkValuePassHelper>::New();
}
//-----------------------------------------------------------------------------
......@@ -579,9 +580,15 @@ void vtkOpenGLPolyDataMapper::ReplaceShaderColor(
// the following are always defined variables. We start
// by assiging a default value from the uniform
std::string colorImpl =
"vec3 ambientColor;\n"
" vec3 ambientColor;\n"
" vec3 diffuseColor;\n"
" float opacity;\n";
if (this->ValuePassHelper->GetRenderingMode() == vtkValuePass::FLOATING_POINT)
{
this->ValuePassHelper->UpdateShaders(VSSource, FSSource, colorImpl);
}
if (this->LastLightComplexity[this->LastBoundBO])
{
colorImpl +=
......@@ -793,6 +800,8 @@ void vtkOpenGLPolyDataMapper::ReplaceShaderLight(
int lastLightComplexity = this->LastLightComplexity[this->LastBoundBO];
if (info && info->Has(vtkValuePass::RENDER_VALUES()))
{
// Although vtkValuePass::FLOATING_POINT does not require this, it is for
// simplicity left unchanged (only required when using INVERTIBLE_LUT mode).
lastLightComplexity = 0;
}
......@@ -1478,6 +1487,16 @@ void vtkOpenGLPolyDataMapper::ReplaceShaderValues(
//cout << "VS: " << shaders[vtkShader::Vertex]->GetSource() << endl;
//cout << "GS: " << shaders[vtkShader::Geometry]->GetSource() << endl;
//cout << "FS: " << shaders[vtkShader::Fragment]->GetSource() << endl;
// std::string vertexShader = shaders[vtkShader::Vertex]->GetSource();
// std::string fragmentShader = shaders[vtkShader::Fragment]->GetSource();
// std::ofstream file("/home/alvaro/testShaders/PolyData_valuePass.frag");
// file << fragmentShader;
// file.close();
//
// file.open("/home/alvaro/testShaders/PolyData_valuePass.vert");
// file << vertexShader;
// file.close();
}
//-----------------------------------------------------------------------------
......@@ -1597,6 +1616,32 @@ void vtkOpenGLPolyDataMapper::UpdateShaders(
this->BuildShaders(shaders, ren, actor);
// vtkInformation *info = actor->GetPropertyKeys();
// if (info && info->Has(vtkValuePass::RENDER_VALUES()))
// {
// // Load shaders
// //---------------
// std::string path = "/home/alvaro/testShaders/";
// std::string filename = "pv_values";
//
// std::string vfilepath = path + filename + ".vert";
// std::ifstream file(vfilepath.c_str());
// std::string vert = std::string(std::istreambuf_iterator<char>(file),
// std::istreambuf_iterator<char>());
// file.close();
//
// std::string ffilepath = path + filename + ".frag";
// file.open(ffilepath.c_str());
// std::string frag = std::string(std::istreambuf_iterator<char>(file),
// std::istreambuf_iterator<char>());
// file.close();
//
// shaders[vtkShader::Vertex]->SetSource(vert);
// shaders[vtkShader::Fragment]->SetSource(frag);
// }
// compile and bind the program if needed
vtkShaderProgram *newShader =
renWin->GetShaderCache()->ReadyShaderProgram(shaders);
......@@ -1694,6 +1739,12 @@ void vtkOpenGLPolyDataMapper::SetMapperShaderParameters(vtkOpenGLHelper &cellBO,
vtkErrorMacro(<< "Error setting 'appleBugPrimID' in shader VAO.");
}
}
if (this->ValuePassHelper->GetRenderingMode() == vtkValuePass::FLOATING_POINT)
{
this->ValuePassHelper->BindValueBuffer(cellBO);
}
cellBO.AttributeUpdateTime.Modified();
}
......@@ -2291,6 +2342,11 @@ void vtkOpenGLPolyDataMapper::RenderPieceStart(vtkRenderer* ren, vtkActor *actor
this->CellNormalTexture->Activate();
}
if (this->ValuePassHelper->GetRenderingMode() == vtkValuePass::FLOATING_POINT)
{
this->ValuePassHelper->UploadValueData(actor, this->CurrentInput);
}
// If we are coloring by texture, then load the texture map.
// Use Map as indicator, because texture hangs around.
if (this->ColorTextureMap)
......@@ -2640,22 +2696,10 @@ void vtkOpenGLPolyDataMapper::ComputeBounds()
//-------------------------------------------------------------------------
void vtkOpenGLPolyDataMapper::UpdateBufferObjects(vtkRenderer *ren, vtkActor *act)
{
// First check if the color mapping needs to be changed
vtkInformation *info = act->GetPropertyKeys();
if (info && info->Has(vtkValuePass::RENDER_VALUES()))
{
this->UseInvertibleColorFor(this->CurrentInput,
info->Get(vtkValuePass::SCALAR_MODE()),
info->Get(vtkValuePass::ARRAY_MODE()),
info->Get(vtkValuePass::ARRAY_ID()),
info->Get(vtkValuePass::ARRAY_NAME()),
info->Get(vtkValuePass::ARRAY_COMPONENT()),
info->Get(vtkValuePass::SCALAR_RANGE()));
}
else
{
this->ClearInvertibleColor();
}
// Checks for the pass's rendering mode and updates its configuration.
// Depending on the case, updates the mapper's color mapping or allocates
// a buffer.
this->ValuePassHelper->UpdateConfiguration(ren, act, this);
// Rebuild buffers if needed
if (this->GetNeedToRebuildBufferObjects(ren,act))
......
......@@ -37,6 +37,7 @@ class vtkOpenGLVertexBufferObject;
class vtkTextureObject;
class vtkTransform;
class vtkGenericOpenGLResourceFreeCallback;
class vtkValuePassHelper;
class VTKRENDERINGOPENGL2_EXPORT vtkOpenGLPolyDataMapper : public vtkPolyDataMapper
{
......@@ -182,6 +183,7 @@ public:
* the VBO's shift+scale transform.
*/
void SetVBOShiftScaleMethod(int m);
protected:
vtkOpenGLPolyDataMapper();
~vtkOpenGLPolyDataMapper();
......@@ -436,6 +438,7 @@ protected:
char *FragmentShaderCode;
char *GeometryShaderCode;
unsigned int TimerQuery;
vtkSmartPointer<vtkValuePassHelper> ValuePassHelper;
private:
vtkOpenGLPolyDataMapper(const vtkOpenGLPolyDataMapper&) VTK_DELETE_FUNCTION;
......
......@@ -25,9 +25,15 @@
#include "vtkRenderer.h"
#include "vtkRenderState.h"
#include "vtkSmartPointer.h"
#include "vtkRenderbuffer.h"
#include "vtkRenderWindow.h"
#include "vtkFloatArray.h"
#include "vtkOpenGLError.h"
#include "vtkOpenGLRenderWindow.h"
#include "vtkFrameBufferObject2.h"
#include <cassert>
#include <vector>
vtkStandardNewMacro(vtkValuePass);
......@@ -50,8 +56,10 @@ public:
int Component;
double ScalarRange[2];
bool ScalarRangeSet;
vtkSmartPointer<vtkClearRGBPass> ClearPass;
vtkInternals()
: ClearPass(vtkSmartPointer<vtkClearRGBPass>::New())
{
this->FieldAssociation = 0;
this->FieldAttributeType = 0;
......@@ -66,8 +74,15 @@ public:
// ----------------------------------------------------------------------------
vtkValuePass::vtkValuePass()
: RenderingMode(1)
, ValueRenderBO(NULL)
, ValueFrameBO(NULL)
, ValuePassResourcesAllocated(false)
{
this->Internals = new vtkInternals();
this->Size[0] = 0;
this->Size[1] = 0;
}
// ----------------------------------------------------------------------------
......@@ -144,12 +159,17 @@ void vtkValuePass::Render(const vtkRenderState *s)
{
assert("pre: s_exists" && s!=0);
vtkSmartPointer<vtkClearRGBPass> clear =
vtkSmartPointer<vtkClearRGBPass>::New();
clear->Render(s);
this->BeginPass(s->GetRenderer());
this->Internals->ClearPass->Render(s);
this->NumberOfRenderedProps=0;
this->RenderOpaqueGeometry(s);
// vtkFrameBufferObject2 is not supported
//s->SetFrameBuffer(this->ValueFrameBO);
this->EndPass();
}
// ----------------------------------------------------------------------------
......@@ -181,7 +201,7 @@ void vtkValuePass::RenderOpaqueGeometry(const vtkRenderState *s)
{
keys.TakeReference(vtkInformation::New());
}
keys->Set(vtkValuePass::RENDER_VALUES(), 1);
keys->Set(vtkValuePass::RENDER_VALUES(), this->RenderingMode);
keys->Set(vtkValuePass::SCALAR_MODE(), this->Internals->FieldAssociation);
keys->Set(vtkValuePass::ARRAY_MODE(), this->Internals->FieldNameSet);
keys->Set(vtkValuePass::ARRAY_ID(), this->Internals->FieldAttributeType);
......@@ -221,3 +241,176 @@ void vtkValuePass::RenderOpaqueGeometry(const vtkRenderState *s)
++i;
}
}
//------------------------------------------------------------------------------
void vtkValuePass::BeginPass(vtkRenderer* ren)
{
switch(this->RenderingMode)
{
case vtkValuePass::FLOATING_POINT:
// Allocate if necessary and bind frame buffer.
this->InitializeFloatingPointMode(ren);
this->ValueFrameBO->Bind(GL_DRAW_FRAMEBUFFER);
break;
case vtkValuePass::INVERTIBLE_LUT:
default:
// Cleanup in case FLOATING_POINT was active.
this->ReleaseFloatingPointMode(ren);
break;
}
}
//------------------------------------------------------------------------------
void vtkValuePass::EndPass()
{
switch(this->RenderingMode)
{
case vtkValuePass::FLOATING_POINT:
// Unbind the float FBO and glReadPixels to host side.
this->ValueFrameBO->UnBind(GL_DRAW_FRAMEBUFFER);
break;
case vtkValuePass::INVERTIBLE_LUT:
default:
// Nothing to do in this mode.
break;
}
}
//------------------------------------------------------------------------------
void vtkValuePass::InitializeFloatingPointMode(vtkRenderer* ren)
{
if (this->ValuePassResourcesAllocated)
return;
vtkRenderWindow* renWin = ren->GetRenderWindow();
if (!this->IsFloatFBOSupported(renWin))
return;
// Allocate FBO's Color attachment target
int* size = ren->GetSize();
this->Size[0] = size[0];
this->Size[1] = size[1];
this->ValueRenderBO = vtkRenderbuffer::New();
this->ValueRenderBO->SetContext(renWin);
this->ValueRenderBO->CreateColorAttachment(this->Size[0], this->Size[1]);
// Initialize the FBO into which the float value pass is rendered.
this->ValueFrameBO = vtkFrameBufferObject2::New();
this->ValueFrameBO->SetContext(renWin);
this->ValueFrameBO->Bind(GL_FRAMEBUFFER);
this->ValueFrameBO->InitializeViewport(this->Size[0], this->Size[1]);
/* GL_COLOR_ATTACHMENT0 */
this->ValueFrameBO->AddColorAttachment(GL_FRAMEBUFFER, 0, this->ValueRenderBO);
// Verify FBO
if(!this->ValueFrameBO->CheckFrameBufferStatus(GL_FRAMEBUFFER))
{
vtkErrorMacro("Failed to attach FBO.");
this->ReleaseFloatingPointMode(ren);
}
this->ValueFrameBO->UnBind(GL_FRAMEBUFFER);
this->ValuePassResourcesAllocated = true;
}
//-----------------------------------------------------------------------------
void vtkValuePass::ReleaseFloatingPointMode(vtkRenderer* ren)
{
if (!this->ValuePassResourcesAllocated)
return;
vtkRenderWindow* renWin = ren->GetRenderWindow();
renWin->MakeCurrent();
// Cleanup FBO (grahpics resources cleaned internally)
this->ValueFrameBO->Delete();
this->ValueFrameBO = NULL;
this->ValueRenderBO->Delete();
this->ValueRenderBO = NULL;
this->ValuePassResourcesAllocated = false;
}
//-----------------------------------------------------------------------------
bool vtkValuePass::IsFloatFBOSupported(vtkRenderWindow *renWin)
{
vtkOpenGLRenderWindow *context = vtkOpenGLRenderWindow::SafeDownCast(renWin);
if (!context)
{
vtkErrorMacro(<< "Support for " << renWin->GetClassName()
<< " not implemented");
return false;
}
#if GL_ES_VERSION_2_0 != 1
bool contextSupport = vtkOpenGLRenderWindow::GetContextSupportsOpenGL32();
if (!contextSupport)
{
vtkWarningMacro(<< "Context does not support OpenGL core profile 3.2. "
<< " Will check extension support.");
}
bool extSupport = glewIsSupported("GL_EXT_framebuffer_object") &&
glewIsSupported("GL_ARB_texture_float");
if (!extSupport)
{
vtkWarningMacro(<< "EXT_framebuffer_object or ARB_texture_float not"
<< " supported.");
}
return contextSupport || extSupport;
#else
return true;
#endif
}
//------------------------------------------------------------------------------