Filter Chain Shaders
A series of image filtering shaders can be grouped and applied sequentially to an image. To do so, add each shader to an IDLgrFilterChain object, which is a specialized type of container designed to hold IDLgrShader objects or objects that subclass from IDLgrShader. Then associate the IDLgrFilterChain object with the IDLgrImage object using the SHADER property.
When the scene is drawn, the image data is modified by each shader program according to container order. The output from the first shader is processed by each subsequent shader until all shader programs have been applied. IDL then draws the result to the window.
Note
This functionality requires support for GLSL frame buffer object extension in addition to the standard hardware support required by IDLgrShader. See the IDLgrWindow::GetDeviceInfo methods's FRAMEBUFFER_OBJECT_EXTENSION keyword for details).
The following example creates an IDLgrFilterChain object and lets you add and remove individual IDLgrShaderConvol3 objects, which provide the ability to apply sharpening, smoothing, and edge detection convolution filters to an image. Like the IDLgrShaderBytscl object, the pre-defined IDLgrShaderConvol3 object includes a software fallback that is automatically used when there is not sufficient hardware support for shader operations.
Example Code
See shader_filterchain_doc__define.pro, located in the examples/doc/shaders subdirectory of the IDL distribution, for the complete, working example. Run the example by entering obj=OBJ_NEW('shader_filterchain_doc') at the IDL command prompt or view the file in an IDL Editor window by entering .EDIT shader_filterchain_doc__define.pro.
Basic Filter Chain Shader Object Class
The shader_filterchain_doc object class inherits from IDLgrFilterChain, which inherits container manipulation methods from IDL_Container, but also includes the FORCE_FILTER method common to IDLgrShader. This means that you can test any software based alternative code provided in a shader's Filter method as described in Providing a Software Alternative to Shaders. Since this example uses the pre-defined IDLgrShaderConvol3 object, there is no need to specify vertex or fragment programs since these are inherent to the object definition.
In addition to the typical object definition code, this example creates instances of the four types of pre-defined convolution filters and stores them in an object array:
oIdentity = OBJ_NEW("IDLgrShaderConvol3", KERNEL=0)
oSmooth = OBJ_NEW("IDLgrShaderConvol3", KERNEL=1)
oSharpen = OBJ_NEW("IDLgrShaderConvol3", KERNEL=2)
oEdge = OBJ_NEW("IDLgrShaderConvol3", KERNEL=3)
objarray = [oIdentity, oSmooth, oSharpen, oEdge]
Since an unmodified image is loaded first, make sure the identity convolution filter is the only item in the filter chain object (self in the following lines). Then associate the IDLgrFilterChain object with the image using the SHADER property.
In this program, you can select among four check boxes to apply varying combinations of convolution filters to a grayscale image. Each time you select a different check box, the list of shaders are removed from the IDLgrFilterChain container and then the selected items are re-added.
; Remove all items from the collection and add back ; selected shaders. self->Remove, /ALL selected = WHERE (value EQ 1) IF N_ELEMENTS(selected) GT 1 || selected NE -1 THEN BEGIN self->Add, (*pstate).objarray[where (value EQ 1)] ENDIF ; Update base and covolution factors for all ; selected shaders. shaderObjs=self->Get(/ALL, COUNT=count) FOR i =0, count-1 DO BEGIN shaderObjs[i]->SetProperty, BASE_BLEND_FACTOR=(*pState).basefactor, $ CONVOL_BLEND_FACTOR=(*pState).convolfactor ENDFOR ; Draw. (*pState).oWindow->Draw, (*pState).oViewNote
Shaders are applied in container order. You could use different user interface controls to provide a way to apply shaders in a specific order instead of using check boxes.
Uniform Variables for Filter Chain Example
There are no exposed uniform variables since the IDLgrShaderConvol3 object exposes its uniform variables as properties. When you call SetProperty for one of the convolution shader's properties, it calls SetUniformVariable internally. See "IDLgrShaderConvol3 Properties" (IDL Reference Guide) for information on the BASE_BLEND_FACTOR, CONVOL_BLEND_FACTOR, and KERNEL properties. If you look in idlgrshaderconvol3__define.pro located in the lib subdirectory of the IDL distribution, you will see the following uniform variables in the fragment shader program:
uniform sampler2D _IDL_ImageTexture uniform float BaseBlend uniform float ConvolBlend uniform vec2 _IDL_ImageStep uniform vec4 kernel[9]
The BaseBlend, ConvolBlend and kernel variables relate to object properties. The _IDL_ImageTexture refers to the base IDLgrImage object and _IDL_ImageStep is used by the convolution filtering operation. Both are reserved uniform variables (see Reserved Uniform Variables for details).
Hardware Shader Program for Filter Chain Example
The fragment and vertex shader programs are incorporated into the IDLgrShaderConvol3 object definition file, idlgrshaderconvol3__define.pro, located in the lib subdirectory of the IDL distribution.
Software Fallback for the Filter Chain Shader
The IDLgrShaderConvol3 object definition file includes a software fallback option that can be exercised using the IDLgrFilterChain FORCE_FILTER property. Set the property either on object creation or in the FilterChain object's Init method. For example, to use the shader_filterchain_doc example with the software fallback, create the object as follows:
Switching the value of the FORCE_FILTER property between 0 and 1 in this example allows you to see the execution speed differences between the hardware and software versions of the filter chain.
When you create a shader_filterchain_doc object and select mineral.png, you can apply one or more convolution shaders and modify shader parameters as shown in the following figure.
