diff --git a/Rendering/Volume/Testing/Cxx/CMakeLists.txt b/Rendering/Volume/Testing/Cxx/CMakeLists.txt index 3c88141d519263fafc229593a17ee385ca6af32d..7f73a557fb74fd8bbba4fd4789a9bea9c12eeba3 100644 --- a/Rendering/Volume/Testing/Cxx/CMakeLists.txt +++ b/Rendering/Volume/Testing/Cxx/CMakeLists.txt @@ -60,9 +60,12 @@ set (VolumeOpenGL2CxxTests TestGPURayCastClipping.cxx TestGPURayCastClippingPolyData.cxx TestGPURayCastClippingUserTransform.cxx + TestGPURayCastDependentComponentsLightParameters.cxx TestGPURayCastFourComponentsDependentGradient.cxx TestGPURayCastGradientOpacity.cxx TestGPURayCastGradientOpacityLight.cxx + TestGPURayCastIndependentComponentsLightParameters.cxx + TestGPURayCastLargeColorTransferFunction.cxx TestGPURayCastPositionalLights.cxx TestGPURayCastReleaseResources.cxx TestGPURayCastRenderDepthToImage.cxx @@ -79,10 +82,9 @@ set (VolumeOpenGL2CxxTests TestGPURayCastVolumePolyData.cxx TestGPURayCastVolumeRotation.cxx TestGPURayCastVolumeScale.cxx - TestProjectedTetrahedraTransform.cxx TestProjectedTetrahedraOffscreen.cxx + TestProjectedTetrahedraTransform.cxx TestRemoveVolumeNonCurrentContext.cxx - TestGPURayCastLargeColorTransferFunction.cxx ) # everyone gets these tests diff --git a/Rendering/Volume/Testing/Cxx/TestGPURayCastDependentComponentsLightParameters.cxx b/Rendering/Volume/Testing/Cxx/TestGPURayCastDependentComponentsLightParameters.cxx new file mode 100644 index 0000000000000000000000000000000000000000..bf4cdd53e657ec67902e562da9139cc80fed034a --- /dev/null +++ b/Rendering/Volume/Testing/Cxx/TestGPURayCastDependentComponentsLightParameters.cxx @@ -0,0 +1,120 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: TestGPURayCastDependentComponentsLightParameters.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. + +=========================================================================*/ + +// This test volume renders the vase dataset with 4 dependent components the +// composite method with shading and light parameters. + +#include "vtkGPUVolumeRayCastMapper.h" +#include "vtkTestUtilities.h" +#include "vtkXMLImageDataReader.h" +#include "vtkImageShiftScale.h" +#include "vtkColorTransferFunction.h" +#include "vtkPiecewiseFunction.h" +#include "vtkTransform.h" +#include "vtkRenderer.h" +#include "vtkRenderWindow.h" +#include "vtkRenderWindowInteractor.h" +#include "vtkVolumeProperty.h" +#include "vtkCamera.h" +#include "vtkRegressionTestImage.h" + +int TestGPURayCastDependentComponentsLightParameters(int argc, + char *argv[]) +{ + cout << "CTEST_FULL_OUTPUT (Avoid ctest truncation of output)" << endl; + char *cfname= + vtkTestUtilities::ExpandDataFileName(argc, argv, "Data/vase_4comp.vti"); + + vtkXMLImageDataReader *reader=vtkXMLImageDataReader::New(); + reader->SetFileName(cfname); + delete [] cfname; + + vtkRenderer *ren1=vtkRenderer::New(); + vtkRenderWindow *renWin=vtkRenderWindow::New(); + renWin->AddRenderer(ren1); + renWin->SetSize(301,300); + vtkRenderWindowInteractor *iren=vtkRenderWindowInteractor::New(); + iren->SetRenderWindow(renWin); + + renWin->Render(); + + vtkGPUVolumeRayCastMapper *volumeMapper; + vtkVolumeProperty *volumeProperty; + vtkVolume *volume; + + volumeMapper=vtkGPUVolumeRayCastMapper::New(); + volumeMapper->SetBlendModeToComposite(); + volumeMapper->SetInputConnection( + reader->GetOutputPort()); + + vtkPiecewiseFunction *opacity=vtkPiecewiseFunction::New(); + opacity->AddPoint(0,0); + opacity->AddPoint(255,1); + + volumeProperty=vtkVolumeProperty::New(); + volumeProperty->IndependentComponentsOff(); + volumeProperty->ShadeOn(); + volumeProperty->SetScalarOpacity(opacity); + volumeProperty->SetAmbient(0.1); + volumeProperty->SetDiffuse(0.9); + volumeProperty->SetSpecular(0.4); + volumeProperty->SetSpecularPower(10.0); + + volume=vtkVolume::New(); + volume->SetMapper(volumeMapper); + volume->SetProperty(volumeProperty); + ren1->AddViewProp(volume); + + int valid=volumeMapper->IsRenderSupported(renWin,volumeProperty); + + int retVal; + if(valid) + { + iren->Initialize(); + ren1->SetBackground(0.1,0.4,0.2); + ren1->ResetCamera(); + renWin->Render(); + retVal = vtkTesting::Test(argc, argv, renWin, 75); + if (retVal == vtkRegressionTester::DO_INTERACTOR) + { + iren->Start(); + } + } + else + { + retVal=vtkTesting::PASSED; + cout << "Required extensions not supported." << endl; + } + + iren->Delete(); + renWin->Delete(); + ren1->Delete(); + volumeMapper->Delete(); + volumeProperty->Delete(); + volume->Delete(); + + opacity->Delete(); + + reader->Delete(); + + if ((retVal == vtkTesting::PASSED) || (retVal == vtkTesting::DO_INTERACTOR)) + { + return 0; + } + else + { + return 1; + } +} diff --git a/Rendering/Volume/Testing/Cxx/TestGPURayCastIndependentComponentsLightParameters.cxx b/Rendering/Volume/Testing/Cxx/TestGPURayCastIndependentComponentsLightParameters.cxx new file mode 100644 index 0000000000000000000000000000000000000000..2db6b008e1152d767d09cca9ef8032a91a95a774 --- /dev/null +++ b/Rendering/Volume/Testing/Cxx/TestGPURayCastIndependentComponentsLightParameters.cxx @@ -0,0 +1,209 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: TestGPURayCastIndependentComponentsLightParameters.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 +// This test creates a vtkImageData with three components. +// The data is volume rendered considering the three components as independent +// with shading and complex light parameters. + +#include "vtkCamera.h" +#include "vtkColorTransferFunction.h" +#include "vtkGPUVolumeRayCastMapper.h" +#include "vtkImageData.h" +#include "vtkInteractorStyleTrackballCamera.h" +#include "vtkNew.h" +#include "vtkPiecewiseFunction.h" +#include "vtkRegressionTestImage.h" +#include "vtkRenderWindow.h" +#include "vtkRenderWindowInteractor.h" +#include "vtkRenderer.h" +#include "vtkSphere.h" +#include "vtkVolume.h" +#include "vtkVolumeProperty.h" + +int TestGPURayCastIndependentComponentsLightParameters(int argc, char *argv[]) +{ + cout << "CTEST_FULL_OUTPUT (Avoid ctest truncation of output)" << endl; + + int dims[3] = {100, 100, 100}; + + // Create a vtkImageData with two components + vtkNew<vtkImageData> image; + image->SetDimensions(dims[0], dims[1], dims[2]); + image->AllocateScalars(VTK_DOUBLE, 3); + + // Fill the first half rectangular parallelopiped along X with the + // first component values and the second half with second component values + double * ptr = static_cast<double *> (image->GetScalarPointer(0, 0, 0)); + + double center1[3], center2[3], center3[3]; + center1[0] = dims[0]/3; center2[0] = center1[0]*2; center3[0] = dims[0]/2; + center1[1] = center2[1] = dims[1]/2; center3[1] = dims[1]/3; + center1[2] = center2[2] = center3[2] = dims[2]/2; + + double radius; + radius = center1[0]; + + vtkNew<vtkSphere> sphere1; + sphere1->SetCenter(center1); + sphere1->SetRadius(radius); + vtkNew<vtkSphere> sphere2; + sphere2->SetCenter(center2); + sphere2->SetRadius(radius); + vtkNew<vtkSphere> sphere3; + sphere3->SetCenter(center3); + sphere3->SetRadius(radius); + + for (int z = 0; z < dims[2]; ++z) + { + for (int y = 0; y < dims[1]; ++y) + { + for (int x = 0; x < dims[0]; ++x) + { + // Set first component + if (sphere1->EvaluateFunction(x, y, z) > 0) + { + // point outside sphere 1 + *ptr++ = 0.0; + } + else + { + *ptr++ = 0.33; + } + // Set second component + if (sphere2->EvaluateFunction(x, y, z) > 0) + { + // point outside sphere 2 + *ptr++ = 0.0; + } + else + { + *ptr++ = 0.33; + } + // Set third component + if (sphere3->EvaluateFunction(x, y, z) > 0) + { + // point outside sphere 2 + *ptr++ = 0.0; + } + else + { + *ptr++ = 0.33; + } + } + } + } + + vtkNew<vtkRenderWindow> renWin; + renWin->SetSize(301, 300); // Intentional NPOT size + renWin->SetMultiSamples(0); + + vtkNew<vtkRenderer> ren; + renWin->AddRenderer(ren.GetPointer()); + + vtkNew<vtkRenderWindowInteractor> iren; + vtkNew<vtkInteractorStyleTrackballCamera> style; + iren->SetInteractorStyle(style.GetPointer()); + iren->SetRenderWindow(renWin.GetPointer()); + + renWin->Render(); + + // Volume render the dataset + vtkNew<vtkGPUVolumeRayCastMapper> mapper; + mapper->AutoAdjustSampleDistancesOff(); + mapper->SetSampleDistance(0.9); + mapper->SetInputData(image.GetPointer()); + + // Color transfer function + vtkNew<vtkColorTransferFunction> ctf1; + ctf1->AddRGBPoint(0.0, 0.0, 0.0, 0.0); + ctf1->AddRGBPoint(1.0, 0.0, 1.0, 0.0); + + vtkNew<vtkColorTransferFunction> ctf2; + ctf2->AddRGBPoint(0.0, 0.0, 0.0, 0.0); + ctf2->AddRGBPoint(1.0, 0.0, 1.0, 0.0); + + vtkNew<vtkColorTransferFunction> ctf3; + ctf3->AddRGBPoint(0.0, 0.0, 0.0, 0.0); + ctf3->AddRGBPoint(1.0, 0.0, 1.0, 0.0); + + // Opacity functions + vtkNew<vtkPiecewiseFunction> pf1; + pf1->AddPoint(0.0, 0.0); + pf1->AddPoint(1.0, 0.2); + + vtkNew<vtkPiecewiseFunction> pf2; + pf2->AddPoint(0.0, 0.0); + pf2->AddPoint(1.0, 0.2); + + vtkNew<vtkPiecewiseFunction> pf3; + pf3->AddPoint(0.0, 0.0); + pf3->AddPoint(1.0, 0.2); + + // Volume property with independent components ON + vtkNew<vtkVolumeProperty> property; + property->IndependentComponentsOn(); + + // Set color and opacity functions + property->SetColor(0, ctf1.GetPointer()); + property->SetColor(1, ctf2.GetPointer()); + property->SetColor(2, ctf3.GetPointer()); + property->SetScalarOpacity(0, pf1.GetPointer()); + property->SetScalarOpacity(1, pf2.GetPointer()); + property->SetScalarOpacity(2, pf3.GetPointer()); + + // Define light parameters + property->ShadeOn(); + + property->SetAmbient(0, 0.2); + property->SetDiffuse(0, 0.9); + property->SetSpecular(0, 0.4); + property->SetSpecularPower(0, 10.0); + property->SetAmbient(1, 0.5); + property->SetDiffuse(1, 0.3); + property->SetSpecular(1, 0.1); + property->SetSpecularPower(1, 1.0); + property->SetAmbient(2, 0.7); + property->SetDiffuse(2, 0.9); + property->SetSpecular(2, 0.4); + property->SetSpecularPower(2, 10.0); + + vtkNew<vtkVolume> volume; + volume->SetMapper(mapper.GetPointer()); + volume->SetProperty(property.GetPointer()); + ren->AddVolume(volume.GetPointer()); + + ren->ResetCamera(); + + iren->Initialize(); + renWin->Render(); + + ren->GetActiveCamera()->Zoom(1.5); + + int retVal = vtkTesting::Test(argc, argv, renWin.GetPointer(), 15); + if (retVal == vtkRegressionTester::DO_INTERACTOR) + { + iren->Start(); + } + + if ((retVal == vtkTesting::PASSED) || (retVal == vtkTesting::DO_INTERACTOR)) + { + return EXIT_SUCCESS; + } + else + { + return EXIT_FAILURE; + } +} diff --git a/Rendering/Volume/Testing/Data/Baseline/TestGPURayCastDependentComponentsLightParameters.png.md5 b/Rendering/Volume/Testing/Data/Baseline/TestGPURayCastDependentComponentsLightParameters.png.md5 new file mode 100644 index 0000000000000000000000000000000000000000..97eb0a544f8eb344d3eb70e8516216812ee0bbe3 --- /dev/null +++ b/Rendering/Volume/Testing/Data/Baseline/TestGPURayCastDependentComponentsLightParameters.png.md5 @@ -0,0 +1 @@ +fe619da74c050bd7dfa273a6de98655b diff --git a/Rendering/Volume/Testing/Data/Baseline/TestGPURayCastIndependentComponentsLightParameters.png.md5 b/Rendering/Volume/Testing/Data/Baseline/TestGPURayCastIndependentComponentsLightParameters.png.md5 new file mode 100644 index 0000000000000000000000000000000000000000..abaf38bad994cc082ab99d347fe511126bf29d1f --- /dev/null +++ b/Rendering/Volume/Testing/Data/Baseline/TestGPURayCastIndependentComponentsLightParameters.png.md5 @@ -0,0 +1 @@ +64475ab80f03db3b202edac5c492a421 diff --git a/Rendering/VolumeOpenGL2/vtkOpenGLGPUVolumeRayCastMapper.cxx b/Rendering/VolumeOpenGL2/vtkOpenGLGPUVolumeRayCastMapper.cxx index 798b925c164caf72b82c7dbdf0470b9dfed239ce..d9d4684c1d1014fd048daa92d5c4309ac24901a2 100644 --- a/Rendering/VolumeOpenGL2/vtkOpenGLGPUVolumeRayCastMapper.cxx +++ b/Rendering/VolumeOpenGL2/vtkOpenGLGPUVolumeRayCastMapper.cxx @@ -3012,23 +3012,23 @@ void vtkOpenGLGPUVolumeRayCastMapper::BuildShader(vtkRenderer* ren, if (this->Impl->CurrentSelectionPass != (vtkHardwareSelector::MIN_KNOWN_PASS - 1)) { switch(this->Impl->CurrentSelectionPass) - { - case vtkHardwareSelector::ID_LOW24: - fragmentShader = vtkvolume::replace(fragmentShader, "//VTK::Picking::Exit", - vtkvolume::PickingIdLow24PassExit(ren, this, vol), true); - break; - case vtkHardwareSelector::ID_MID24: - fragmentShader = vtkvolume::replace(fragmentShader, "//VTK::Picking::Exit", - vtkvolume::PickingIdMid24PassExit(ren, this, vol), true); - break; - default: // ACTOR_PASS, PROCESS_PASS - fragmentShader = vtkvolume::replace(fragmentShader, "//VTK::Picking::Dec", - vtkvolume::PickingActorPassDeclaration(ren, this, vol), true); + { + case vtkHardwareSelector::ID_LOW24: + fragmentShader = vtkvolume::replace(fragmentShader, "//VTK::Picking::Exit", + vtkvolume::PickingIdLow24PassExit(ren, this, vol), true); + break; + case vtkHardwareSelector::ID_MID24: + fragmentShader = vtkvolume::replace(fragmentShader, "//VTK::Picking::Exit", + vtkvolume::PickingIdMid24PassExit(ren, this, vol), true); + break; + default: // ACTOR_PASS, PROCESS_PASS + fragmentShader = vtkvolume::replace(fragmentShader, "//VTK::Picking::Dec", + vtkvolume::PickingActorPassDeclaration(ren, this, vol), true); - fragmentShader = vtkvolume::replace(fragmentShader, "//VTK::Picking::Exit", - vtkvolume::PickingActorPassExit(ren, this, vol), true); - break; - } + fragmentShader = vtkvolume::replace(fragmentShader, "//VTK::Picking::Exit", + vtkvolume::PickingActorPassExit(ren, this, vol), true); + break; + } } // Render to texture @@ -3576,17 +3576,26 @@ void vtkOpenGLGPUVolumeRayCastMapper::DoGPURender(vtkRenderer* ren, //-------------------------------------------------------------------------- this->Impl->SetLightingParameters(ren, prog, vol); - fvalue3[0] = fvalue3[1] = fvalue3[2] = volumeProperty->GetAmbient(); - prog->SetUniform3f("in_ambient", fvalue3); - - fvalue3[0] = fvalue3[1] = fvalue3[2] = volumeProperty->GetDiffuse(); - prog->SetUniform3f("in_diffuse", fvalue3); + float ambient[4][3]; + float diffuse[4][3]; + float specular[4][3]; + float specularPower[4]; - fvalue3[0] = fvalue3[1] = fvalue3[2] = volumeProperty->GetSpecular(); - prog->SetUniform3f("in_specular", fvalue3); + for (int i = 0; i < numberOfSamplers; ++i) + { + ambient[i][0] = ambient[i][1] = ambient[i][2] = + volumeProperty->GetAmbient(i); + diffuse[i][0] = diffuse[i][1] = diffuse[i][2] = + volumeProperty->GetDiffuse(i); + specular[i][0] = specular[i][1] = specular[i][2] = + volumeProperty->GetSpecular(i); + specularPower[i] = volumeProperty->GetSpecularPower(i); + } - fvalue3[0] = volumeProperty->GetSpecularPower(); - prog->SetUniformf("in_shininess", fvalue3[0]); + prog->SetUniform3fv("in_ambient", numberOfSamplers, ambient); + prog->SetUniform3fv("in_diffuse", numberOfSamplers, diffuse); + prog->SetUniform3fv("in_specular", numberOfSamplers, specular); + prog->SetUniform1fv("in_shininess", numberOfSamplers, specularPower); double clippingRange[2]; cam->GetClippingRange(clippingRange); diff --git a/Rendering/VolumeOpenGL2/vtkVolumeShaderComposer.h b/Rendering/VolumeOpenGL2/vtkVolumeShaderComposer.h index 4b3db072bee0741a3a1ee5fa4f2e8c9bf57f4da1..f493876e883e7b3bae1400feaa836d44dde1e5a8 100644 --- a/Rendering/VolumeOpenGL2/vtkVolumeShaderComposer.h +++ b/Rendering/VolumeOpenGL2/vtkVolumeShaderComposer.h @@ -180,10 +180,10 @@ namespace vtkvolume \nuniform vec3 in_textureExtentsMin;\ \n\ \n// Material and lighting\ - \nuniform vec3 in_diffuse;\ - \nuniform vec3 in_ambient;\ - \nuniform vec3 in_specular;\ - \nuniform float in_shininess;\ + \nuniform vec3 in_diffuse[4];\ + \nuniform vec3 in_ambient[4];\ + \nuniform vec3 in_specular[4];\ + \nuniform float in_shininess[4];\ \n\ \n// Others\ \nuniform bool in_cellFlag;\ @@ -616,14 +616,16 @@ namespace vtkvolume \n }\ \n if (nDotL > 0.0)\ \n {\ - \n diffuse = nDotL * in_diffuse * in_lightDiffuseColor[0]\ - \n * color.rgb;\ + \n diffuse = nDotL * in_diffuse[component] *\ + \n in_lightDiffuseColor[0] * color.rgb;\ \n }\ - \n specular = pow(nDotH, in_shininess) * in_specular *\ + \n specular = pow(nDotH, in_shininess[component]) *\ + \n in_specular[component] *\ \n in_lightSpecularColor[0];\ \n // For the headlight, ignore the light's ambient color\ \n // for now as it is causing the old mapper tests to fail\ - \n finalColor.xyz = in_ambient * color.rgb + diffuse + specular;" + \n finalColor.xyz = in_ambient[component] * color.rgb +\ + \n diffuse + specular;" ); } else if (lightingComplexity == 2) @@ -669,13 +671,14 @@ namespace vtkvolume \n }\ \n if (nDotH > 0.0)\ \n {\ - \n specular = in_lightSpecularColor[lightNum] * pow(nDotH, in_shininess);\ + \n specular = in_lightSpecularColor[lightNum] *\ + \n pow(nDotH, in_shininess[component]);\ \n }\ \n ambient += in_lightAmbientColor[lightNum];\ \n }\ - \n finalColor.xyz = in_ambient * ambient +\ - \n in_diffuse * diffuse * color.rgb +\ - \n in_specular * specular;" + \n finalColor.xyz = in_ambient[component] * ambient +\ + \n in_diffuse[component] * diffuse * color.rgb +\ + \n in_specular[component] * specular;" ); } else if (lightingComplexity == 3) @@ -746,13 +749,14 @@ namespace vtkvolume \n }\ \n if (nDotH > 0.0)\ \n {\ - \n float sf = attenuation * pow(nDotH, in_shininess);\ + \n float sf = attenuation * pow(nDotH, in_shininess[component]);\ \n specular += (sf * in_lightSpecularColor[lightNum]);\ \n }\ \n ambient += in_lightAmbientColor[lightNum];\ \n }\ - \n finalColor.xyz = in_ambient * ambient + in_diffuse *\ - \n diffuse * color.rgb + in_specular * specular;\ + \n finalColor.xyz = in_ambient[component] * ambient +\ + \n in_diffuse[component] * diffuse * color.rgb +\ + \n in_specular[component] * specular;\ "); } }