Add GLSL shader to a VTKActor (VTK 6.1) - opengl

I'm trying to add a shader to a vtkActor into my application. I have different vtkActors and they must have different shaders each one.
I tried with the vtkShader2, vtkShaderProgram2 and vtkOpenGLProperty to set the program loaded with the shader to the actor, but it didn't work (vtk told me in a warning window that it has 4 shaders in the actor, the default shaders and mine).
Someone knows the right way to do it?

The solution finally appeared in vtk mailing list after months of waiting! I didn't test it myself, but user #carlinhos says it works. He resumes the steps:
Create a shader file with the function propFuncFS(Fragment shader) or propFuncVS(Vertex shader).
Load the shader from disk.
Create a vtkShader2 and set the source code.
Create a vtkShaderProgram2 and initialize it (DO NOT BUILD THE PROGRAM).
Add the shader to the program.
Obtain the actor vtkOpenGLProperty and set the program
Set the shading on.
EDIT: Is #carlinhos you? I am feeding you your own answer? :)

After running into this myself, I'd like to add a little more to mpcarlos87 / carlinhos / Nil's answer...
The code below is the smallest that I could make an informative working sample. Key points are:
vtkSmartPointer use means less need to clean-up ptrClass->Delete() style
smart pointers also do automatic casting: vtkRenderWindow* to vtkOpenGLRenderWindow* for SetContect(), which is nice
inline frag shader definition is good for fast testing, but bad for every other reason (use with care!)
inline frag shader is very sensitive to new lines (\n) for things like #version
#include "vtkConeSource.h"
#include "vtkPolyDataMapper.h"
#include "vtkRenderWindow.h"
#include "vtkCamera.h"
#include "vtkActor.h"
#include "vtkRenderer.h"
#include "vtkShader2.h"
#include "vtkShaderProgram2.h"
#include "vtkShader2Collection.h"
#include "vtkSmartPointer.h"
#include "vtkOpenGLRenderWindow.h"
#include "vtkOpenGLProperty.h"
int main()
{
vtkSmartPointer<vtkConeSource> cone = vtkConeSource::New();
vtkSmartPointer<vtkPolyDataMapper> coneMapper = vtkPolyDataMapper::New();
coneMapper->SetInputConnection( cone->GetOutputPort() );
vtkSmartPointer<vtkActor> coneActor = vtkActor::New();
coneActor->SetMapper( coneMapper );
vtkSmartPointer<vtkRenderer> ren= vtkRenderer::New();
ren->AddActor( coneActor );
vtkSmartPointer<vtkRenderWindow> renWin = vtkRenderWindow::New();
renWin->AddRenderer( ren );
const char* frag = "void propFuncFS(void){ gl_FragColor = vec4(255,0,0,1);}";
vtkSmartPointer<vtkShaderProgram2> pgm = vtkShaderProgram2::New();
pgm->SetContext(renWin);
vtkSmartPointer<vtkShader2> shader=vtkShader2::New();
shader->SetType(VTK_SHADER_TYPE_FRAGMENT);
shader->SetSourceCode(frag);
shader->SetContext(pgm->GetContext());
pgm->GetShaders()->AddItem(shader);
vtkSmartPointer<vtkOpenGLProperty> openGLproperty =
static_cast<vtkOpenGLProperty*>(coneActor->GetProperty());
openGLproperty->SetPropProgram(pgm);
openGLproperty->ShadingOn();
int i;
for (i = 0; i < 360; ++i)
{
renWin->Render();
ren->GetActiveCamera()->Azimuth( 1 );
}
return 0;
}
Took a bit of trial and error to get the above working - hope that it helps!

Related

GLSL texture returns zero after OpenInventor upgrade from 9.8 to 10.4.2

While upgrading our source code from OpenInventor 9.8 to 10.4.2 I encountered that some color computed in the fragment-shader is always black in 10.4.2 while in 9.8 everything works fine. Normally we use our own computed texture, but for debugging purposes I used an example texture from the OpenInventor examples:
SoSwitch* root = new SoSwitch;
// Fill root with geometry
root->addChild(...)
SoSeparator* localRoot = new SoSeparator;
SoFragmentShader* fragShader = new SoFragmentShader;
SoShaderProgram* shaderProgram = new SoShaderProgram;
SoTexture2 texture = new SoTexture2;
texture->filename = "pathToImage\image.png"
SoTextureUnit textureUnit = new SoTextureUnit;
texture Unit->unit = 1;
localRoot->addChild(textureUnit);
localRoot->addChild(texture);
fragShader->addShaderParameter1i("myTexture", 1);
shaderProgram->shaderObject.set1Value(1, fragShader);
root->addChild(localRoot);
root->addChild(shaderProgram);
This is the fragment-shader which works fine with 9.8:
#version 120
uniform sampler2D myTexture;
in vec3 coord; // Computed in vertex-shader
int main() {
gl_FragColor = texture2D(myTexture, coord.xy);
// For Debugging:
// gl_FragColor = vec4(coord.xy, 0, 1);
}
This is the fragment-shader which does not work with 10.4.2:
#version 410 compatibility
//!oiv_include <Inventor/oivShaderState.h>
//!oiv_include <Inventor/oivShapeAttribute.h>
//!oiv_include <Inventor/oivShaderVariables.h>
uniform sampler2D myTexture;
in vec3 coord;
int main() {
OivFragmentOutput(texture(myTexture, coord.xy)); // Is the same as gl_FragColor =
// For Debugging:
// gl_FragColor = vec4(coord.xy, 0, 1);
}
The viewer stays completely black, so I assume the call to texture returns always zero.
Uncommenting gl_FragColor = vec4(coord.xy, 0, 1); gives the same result. Therefor I assume that coordis computed correctly.
As we are jumping from version #120 to #410, I could imagine that I need to do something else to get texture work in our fragment-shader. Were there any relevant changes in GLSL. What do I need to do to get the shader working?
If relevant, here are some system information:
Operating System: Windows 10
Graphics board: NVIDIA Quadro K2200
The issue here is in your scene graph as both texture and textureUnit nodes are under a SoSeparator and are not visible to the shaderProgam, which is outside the SoSeparator localRoot. Please move these nodes out of localRoot and add them as a child to the root node to render correctly.
It was working for you with Open Inventor 9.8 because of a bug which is fixed since Open Inventor 10. Hope this helps and let us know if the issue is resolved for you.
In future, please feel free to contact Open Inventor support ( FRBOR.3d_hotline#thermofisher.com) with your questions.
Via mail the Open Inventor Support suggested another solution which is also working:
Replace
SoSeparator* localRoot = new SoSeparator;
with
SoGroup* localRoot = new SoGroup;

VTK pipeline update

I use VTK-6.2, C++ (gcc-4.7.2) on Linux and I have the following VTK pipeline setup (please ignore implementation, details and focus on the pipeline: cone->filter->mapper->actor):
// cone/initialize
vtkConeSource cone;
// add cone(s) to filter
vtkAppendFilter filter;
filter.AddInputData(cone.GetOutput());
// add filter to mapper
vtkDataSetMapper mapper;
mapper.SetInputData(filter->GetOutput());
// actor
vtkActor actor;
actor.SetMapper(mapper);
The scene renders fine.
The Problem
I want to update the original data (i.e. the cones) and the actor to be rendered correctly.
How do I access the original cone data if I have just the actors? Does this guarantee that the actors will be updated too? Because when I decided to keep track of the original data (via pointers: the whole implementation is with vtkSmartPointers) and then change some of their attributes, the pipeline did not update. Shouldn't it update automatically?
(When I change the actor (e.g. their visibility), the scene renders fine)
Forgive me, I am not a VTK expert and the pipelines are confusing. Maybe one approach would be to simplify my pipeline.
Thanks
[update]
According to this answer to a similar post, the original data (vtkConeSource) are transformed (to vtkUnstructuredGrid when added in the vtkAppendFilter) so even if I keep track of the original data, changing them is useless.
VTK pipelines are demand-driven pipelines. They do not update automatically even if one of the elements of the pipeline is modified. We need to explicitly call the Update() function on the last vtkAlgorithm( or its derived class object) of the pipeline to update the entire pipeline. The correct way to set up a pipeline is when we are connecting two objects which are derived from vtkAlgorithm type is to use
currAlgoObj->SetInputConnection( prevAlgoObj->GetOutputPort() )
instead of
currAlgoObj->SetInputData( prevAlgo->GetOutput() )
Then we can update the pipeline using the pointer to the actor object by doing actor->GetMapper()->Update() like shown in the example below.
In this example, we will create a cone from a cone source, pass it through vtkAppendFilter and then change the height of the original cone source and render it in another window to see the updated cone. (You will have to close the first render window to see the updated cone in second window.)
#include <vtkConeSource.h>
#include <vtkDataSetMapper.h>
#include <vtkActor.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkSmartPointer.h>
#include <vtkAppendFilter.h>
int main(int, char *[])
{
// Set up the data pipeline
auto cone = vtkSmartPointer<vtkConeSource>::New();
cone->SetHeight( 1.0 );
auto appf = vtkSmartPointer<vtkAppendFilter>::New();
appf->SetInputConnection( cone->GetOutputPort() );
auto coneMapper = vtkSmartPointer<vtkDataSetMapper>::New();
coneMapper->SetInputConnection( appf->GetOutputPort() );
auto coneActor = vtkSmartPointer<vtkActor>::New();
coneActor->SetMapper( coneMapper );
// We need to update the pipeline otherwise nothing will be rendered
coneActor->GetMapper()->Update();
// Connect to the rendering portion of the pipeline
auto renderer = vtkSmartPointer<vtkRenderer>::New();
renderer->AddActor( coneActor );
renderer->SetBackground( 0.1, 0.2, 0.4 );
auto renderWindow = vtkSmartPointer<vtkRenderWindow>::New();
renderWindow->SetSize( 200, 200 );
renderWindow->AddRenderer(renderer);
auto renderWindowInteractor =
vtkSmartPointer<vtkRenderWindowInteractor>::New();
renderWindowInteractor->SetRenderWindow(renderWindow);
renderWindowInteractor->Start();
// Change cone property
cone->SetHeight( 10.0 );
//Update the pipeline using the actor object
coneActor->GetMapper()->Update();
auto renderer2 = vtkSmartPointer<vtkRenderer>::New();
renderer2->AddActor( coneActor );
renderer2->SetBackground( 0.1, 0.2, 0.4 );
auto renderWindow2 = vtkSmartPointer<vtkRenderWindow>::New();
renderWindow2->SetSize( 200, 200 );
renderWindow2->AddRenderer(renderer2);
auto renderWindowInteractor2 =
vtkSmartPointer<vtkRenderWindowInteractor>::New();
renderWindowInteractor2->SetRenderWindow(renderWindow2);
renderWindowInteractor2->Start();
return EXIT_SUCCESS;
}

VTK Toolkit - vtkCutter Performance

I use the VTK Toolkit to load an OBJ file and a vtkCutter to cut through the data set with a play and then draw the outline of the cut. For large objects this is can become quite slow as another user pointed out in the VTK Users Forum.
Is there a way to make the cutter use a hierarchical data structure to gain better performance?
This is the code:
#include <vtkSmartPointer.h>
#include <vtkCubeSource.h>
#include <vtkPolyDataMapper.h>
#include <vtkPlane.h>
#include <vtkCutter.h>
#include <vtkProperty.h>
#include <vtkActor.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkOBJReader.h>
int main(int argc, char *argv[])
{
// Parse command line arguments
if (argc != 2) {
std::cout << "Usage: " << argv[0] << " Filename(.obj)" << std::endl;
return EXIT_FAILURE;
}
std::string filename = argv[1];
vtkSmartPointer<vtkOBJReader> obj = vtkSmartPointer<vtkOBJReader>::New();
obj->SetFileName(filename.c_str());
obj->Update();
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
mapper->SetInputConnection(obj->GetOutputPort());
// Create a plane to cut,here it cuts in the XZ direction (xz normal=(1,0,0);XY =(0,0,1),YZ =(0,1,0)
vtkSmartPointer<vtkPlane> plane = vtkSmartPointer<vtkPlane>::New();
plane->SetOrigin(0, 0, 0);
plane->SetNormal(1, 0, 0);
// Create cutter
vtkSmartPointer<vtkCutter> cutter = vtkSmartPointer<vtkCutter>::New();
cutter->SetCutFunction(plane);
cutter->SetInputConnection(obj->GetOutputPort());
cutter->Update();
vtkSmartPointer<vtkPolyDataMapper> cutterMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
cutterMapper->SetInputConnection(cutter->GetOutputPort());
// Create plane actor
vtkSmartPointer<vtkActor> planeActor = vtkSmartPointer<vtkActor>::New();
planeActor->GetProperty()->SetColor(1.0, 1, 0);
planeActor->GetProperty()->SetLineWidth(2);
planeActor->SetMapper(cutterMapper);
// Create cube actor
vtkSmartPointer<vtkActor> cubeActor = vtkSmartPointer<vtkActor>::New();
cubeActor->GetProperty()->SetColor(0.5, 1, 0.5);
cubeActor->GetProperty()->SetOpacity(0.5);
cubeActor->SetMapper(mapper);
// Create renderers and add actors of plane and cube
vtkSmartPointer<vtkRenderer> renderer = vtkSmartPointer<vtkRenderer>::New();
renderer->AddActor(planeActor); //display the rectangle resulting from the cut
renderer->AddActor(cubeActor); //display the cube
// Add renderer to renderwindow and render
vtkSmartPointer<vtkRenderWindow> renderWindow = vtkSmartPointer<vtkRenderWindow>::New();
renderWindow->AddRenderer(renderer);
renderWindow->SetSize(600, 600);
vtkSmartPointer<vtkRenderWindowInteractor> interactor = vtkSmartPointer<
vtkRenderWindowInteractor>::New();
interactor->SetRenderWindow(renderWindow);
renderer->SetBackground(0, 0, 0);
renderWindow->Render();
interactor->Start();
return EXIT_SUCCESS;
}
vtkCutter slices meshes using an arbitrarily complex func(x,y,z) and is used here with a simple plane to describe that function, which is a common and well covered special case, as the cut countour lies on a simple plane and will hence be a simple (flat) polygon.
These generic implementations usually cost alot of CPU time, because all special cases of poly cutting are expected to occur in case of vtkCutter.
There's also a slowdown coming from calling virtual functions in the vast class hierarchy of VTK. Without special hacks, it solely depends on the compiler to optimize the virtual function pointer lookup out of a loop, while VTK calls virtual functions (the filter function, for example) many times in one or more nested loops.
See this for related info: about the cost of virtual function
VTK uses doubles almost everywhere, even if one could live with floats. Conversion and high precision also add quiet a bit of computation and memory overhead.
VTK (5.8) does not explicitly involve SIMD operations like SSE, afaik.
...
Search for topics like these:
Algorithm or software for slicing a mesh
Generate 2D cross-section polygon from 3D mesh.
Despite doing this on a CPU, one could also use an OpenGL geometry shader in a transform feedback pass to extract the cut contour determined by a cut plane. Doing this in OpenCL is also possible, however, if no GPU based compute device is available, it might get slower than a C or C++ implementation.
To render the meshes, one could use any OpenGL 3+ capable Renderer:
Ogre3D
Unity3D
Irrlicht
OSG
a simple, self made OpenGL 3 renderer.
...
more: What is the best way to have realtime 3D rendering in an engineering application?

Illegal Instruction When Programming C++ on Linux

My program, which does exactly the same thing every time it runs (moves a point sprite into the distance) will randomly fail with the text on the terminal 'Illegal Instruction'. My googling has found people encountering this when writing assembly which makes sense because assembly throws those kinds of errors.
But why would g++ be generating an illegal instruction like this? It's not like I'm compiling for Windows then running on Linux (which even then, as long as both are on x86 shouldn't AFAIK cause an Illegal Instruction). I'll post the main file below.
I can't reliably reproduce the error. Although, if I make random changes (add a space here, change a constant there) that force a recompile I can get a binary which will fail with Illegal Instruction every time it is run, until I try setting a break point, which makes the illegal instruction 'dissapear'. :(
#include <stdio.h>
#include <stdlib.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <SDL/SDL.h>
#include "Screen.h" //Simple SDL wrapper
#include "Textures.h" //Simple OpenGL texture wrapper
#include "PointSprites.h" //Simple point sprites wrapper
double counter = 0;
/* Here goes our drawing code */
int drawGLScene()
{
/* These are to calculate our fps */
static GLint T0 = 0;
static GLint Frames = 0;
/* Move Left 1.5 Units And Into The Screen 6.0 */
glLoadIdentity();
glTranslatef(0.0f, 0.0f, -6);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
glEnable(GL_POINT_SPRITE_ARB);
glTexEnvi(GL_POINT_SPRITE, GL_COORD_REPLACE, GL_TRUE);
glBegin( GL_POINTS ); /* Drawing Using Triangles */
glVertex3d(0.0,0.0, 0);
glVertex3d(1.0,0.0, 0);
glVertex3d(1.0,1.0, counter);
glVertex3d(0.0,1.0, 0);
glEnd( ); /* Finished Drawing The Triangle */
/* Move Right 3 Units */
/* Draw it to the screen */
SDL_GL_SwapBuffers( );
/* Gather our frames per second */
Frames++;
{
GLint t = SDL_GetTicks();
if (t - T0 >= 50) {
GLfloat seconds = (t - T0) / 1000.0;
GLfloat fps = Frames / seconds;
printf("%d frames in %g seconds = %g FPS\n", Frames, seconds, fps);
T0 = t;
Frames = 0;
counter -= .1;
}
}
return 1;
}
GLuint objectID;
int main( int argc, char **argv )
{
Screen screen;
screen.init();
screen.resize(800,600);
LoadBMP("./dist/Debug/GNU-Linux-x86/particle.bmp");
InitPointSprites();
while(true){drawGLScene();}
}
The compiler isn't generating illegal exceptions, with 99.99% probability. Almost certainly what's happening is that you have a bug in your program which is causing it to either a) overwrite parts of your executable code with garbage data, or b) use a function pointer that points into garbage. Try running your program under valgrind to diagnose the problem - http://valgrind.org/.
The Illegal Instruction bug can also be a symptom of a faulty graphics card driver, or one that's mismatched to the hardware. Use lspci | grep VGA to confirm what your hardware actually is. Then try downloading the latest & greatest driver for your hardware model.
There is also a known bug when running code from inside NetBeans 6.8 on a multi-core 64-bit machine. The code crashes stochastically with Illegal Instruction based on race conditions in the profiler. Per cent of crashes varies from 1% or 5% for some code, 30% or 50%, up to around 95%+, depending on which libraries are being loaded. Graphics and threads code seems to increase this, but you can see it with a trivial Hello World main. If you get a 1% crash rate, you probably haven't noticed it before. Solution: run the executable straight from a terminal, if you can.
Most probably your drivers are Mesa Software Rendering or a faulty Graphic Card Driver. Mesa uses sometimes special set of instructions like AVX, AVX2, among others.
Your glEnable(GL_POINT_SPRITE_ARB); code may be activating such a part from Mesa which is not intended for your CPU.
I know the post is old, but might help others in the future.

HLSL and ID3DXFont/ID3DXSprite

I've started at the beginning, and my code will capably display the grand total of some text. I've been adding support for sprites. The trouble that I've run in to, is that it doesn't seem to recognize my HLSL. I set the technique, began it, began the pass, drew the sprites, flushed them, ended the pass, the technique. And D3D comes up with this little "Using FF to PS converter" in the VS output. Same for VS. I'm not trying to do anything advanced with my HLSL - just use it and get a little more familiar with it and make sure I know how to implement it. That's C++0x auto, by the way, so automatic type deduction (because I'm lazy).
#define D3DCALL(a) { auto __ = a; if (FAILED(__)) DXTrace(__FILE__, __LINE__, __, WIDEN(#a), TRUE); }
D3DCALL(spriteeffect->SetTechnique(spritetechnique));
D3DCALL(spriteeffect->Begin(&passes, NULL));
D3DCALL(spriteeffect->BeginPass(0)); // We know this is zero.
D3DCALL(sprite->Begin(D3DXSPRITE_OBJECTSPACE | D3DXSPRITE_DO_NOT_ADDREF_TEXTURE | D3DXSPRITE_SORT_TEXTURE | D3DXSPRITE_ALPHABLEND | D3DXSPRITE_SORT_DEPTH_FRONTTOBACK));
RenderAndCleanUp(common->sprites);
D3DCALL(sprite->End());
D3DCALL(spriteeffect->EndPass());
D3DCALL(spriteeffect->End());
where RenderAndCleanUp is a simple templated function that loops through the sprites, destroys those that need to be, and renders the rest, and common->sprites is a simple vector of all the sprite objects. Since DXTrace never goes off, I'll guarantee that none of the functions fail. I've also set the control panel to max debugging.
I checked the D3DXHANDLEs and they're all non-NULL. It doesn't report any compilation errors, or any errors or warnings.
// Contains the HLSL for sprites.
// Based on transform.fx, by Frank Luna.
// FX parameter (global variable to the shader).
uniform extern float4x4 gWVP;
// Structure
struct OutputVS
{
float4 posH : POSITION0;
float4 color : COLOR0;
};
// Vertex shader
OutputVS SpriteVS(float3 post : POSITION0,
float4 col : COLOR0)
{
// Zero out our output.
OutputVS outVS = (OutputVS)0;
outVS.posH = mul(float4(post, 1.0f), gWVP); // Transform
outVS.color = col;
// Done--return the output.
return outVS;
}
// Pixel shader - take the original colour of the pixel and just return it. Nothing fancy.
float4 SpritePS( float4 col : COLOR0 ) : COLOR
{
return col;
}
technique Sprite
{
pass P0
{
// Specify the vertex and pixel shader associated
// with this pass.
vertexShader = compile vs_3_0 SpriteVS();
pixelShader = compile ps_3_0 SpritePS();
}
}
This is native C++ looking at Direct3D9.
AFAIR D3DXSprite and D3DXFont rendering is implemented inside of D3DX itself. So, it sets its own shaders, states (emulates fixed-function pipeline) and renders text/sprites. So, your shaders and states have no effect on these objects.
You may implement your own text/sprite rendering subsystem, it's not so hard. Another vote for this is that Microsoft officially deprecated D3DX.