Commit da982ebe authored by Sebastian Eichelbaum's avatar Sebastian Eichelbaum
Browse files

[ADD] - improved colormaps. Until now, Grayscale, Pos2Neg and Vector are implemented. More to come.

parent 3c49474d
//---------------------------------------------------------------------------
//
// Project: OpenWalnut ( http://www.openwalnut.org )
//
// Copyright 2009 OpenWalnut Community, BSV-Leipzig and CNCF-CBS
// For more information see http://www.openwalnut.org/copying
//
// This file is part of OpenWalnut.
//
// OpenWalnut is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// OpenWalnut is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
//
//---------------------------------------------------------------------------
#ifndef WGECOLORMAPSIMPROVED_GLSL
#define WGECOLORMAPSIMPROVED_GLSL
#version 120
#include "WGEUtils.glsl"
/**
* Grayscale colormap. Maps value directly to gray values.
*
* \param value the <b>scaled</b> value
*
* \return color. Alpha == 0 if value.r == 0.
*/
vec4 grayscale( in vec3 value )
{
return vec4( value, -1.0 * sign( 0.0 - value.r ) );
}
/**
* Maps red and blue to the positive and negative part of the interval linearly. It handles the zero-point according to specified min and scale
* values.
*
* \note it does not show blue values for data that is purely positive (like T1 images and similar).
*
* \param valueDescaled <b>descaled</b> value
* \param minV min value
* \param scaleV scaling factor
*
* \return pos2neg colormap
*/
vec4 negative2positive( in float valueDescaled, in float minV, in float scaleV )
{
const vec3 zeroColor = vec3( 1.0, 1.0, 1.0 );
const vec3 negColor = vec3( 1.0, 1.0, 0.0 );
const vec3 posColor= vec3( 0.0, 1.0, 1.0 );
// the descaled value can be in interval [minV,minV+Scale]. But as we want linear scaling where the pos and neg colors are scaled linearly
// agains each other, we need the absolut maximum:
float m = max( abs( minV ), abs( minV + scaleV ) );
// find the relative share of the value in the new interval [-m,m]
float share = valueDescaled / m;
// use neg color for shares < 0.0 and pos color for the others
return vec4( zeroColor - ( ( clamp( share, -1.0 , 0.0 ) * negColor ) + ( clamp( share, 0.0 , 1.0 ) * posColor )
), 1.0 );
}
/**
* Vector colormap. This basically is a grayscale colormap for each channel. It additionally clips according to vector length.
*
* \param valueDescaled the <b>descaled</b> vector data
* \param minV minimum value
* \param scaleV scaling value
*
* \return colormap.
*/
vec4 vector( in vec3 valueDescaled, in float minV, in float scaleV )
{
// similar to negative2positive, we need the width of the interval.
float m = max( abs( minV ), abs( minV + scaleV ) );
return vec4( abs( valueDescaled / m ),
// if the vector length is near zero -> clip
clamp( sign( length( valueDescaled ) - 0.01 ), 0.0, 1.0 )
);
}
/**
* The method decides whether the value should be clipped because of the threshold value. This is different for vector and scalar data, which is
* why this method handles it transparently.
*
* \param valueDescaled the descaled data. Scalar or vector.
* \param colormap if this is a vector colormap, thresholding is done using vector length.
*
* \return 0.0 if clipped
*/
float clipThreshold( in vec3 valueDescaled, in int colormap, in float thresholdV )
{
float isVec = float( colormap == 6 );
return isVec * clamp( sign( length( valueDescaled ) - thresholdV ), 0.0, 1.0 )
+
( 1.0 - isVec ) * clamp( sign( valueDescaled.r - thresholdV ), 0.0, 1.0 );
}
/**
* This method applies a colormap to the specified value an mixes it with the specified color. It uses the proper colormap and works on scaled
* values.
*
* \param color this color gets mixed using alpha value with the new colormap color
* \param value the value to map, <b>scaled</b>
* \param minV the minimum of the original value
* \param scaleV the scaler used to downscale the original value to [0-1]
* \param thresholdV a threshold in original space (you need to downscale it to [0-1] if you want to use it to scaled values.
* \param alpha the alpha blending value
* \param colormap the colormap index to use
*/
vec4 colormap( in vec3 value, float minV, float scaleV, float thresholdV, float alpha, int colormap, bool active )
{
// descale value
vec3 valueDescaled = vec3( minV ) + ( value * scaleV );
// this is the final color returned by the colormapping algorithm. This is the correct value for the gray colormap
vec4 cmapped = grayscale( value );
// negative to positive shading in red-blue
if ( colormap == 3 )
{
cmapped = negative2positive( valueDescaled.r, minV, scaleV );
}
else if ( colormap == 6 )
{
cmapped = vector( valueDescaled, minV, scaleV );
}
// build final color
return vec4( cmapped.rgb, cmapped.a * // did the colormap use a alpha value?
alpha * // did the user specified an alpha?
clipThreshold( valueDescaled, colormap, thresholdV ) * // clip due to threshold?
float( active ) ); // is it active?
}
#endif // WGECOLORMAPS_GLSL
......@@ -27,14 +27,14 @@
#version 120
#include "WGEColorMaps.glsl"
#include "WGEColorMapsImproved.glsl"
#include "WGEColormapping-uniforms.glsl"
#include "WGEColormapping-varyings.glsl"
/**
* This method applies a colormap to the specified value an mixes it with the specified color. It uses the proper colormap and is able to unscale
* values if needed.
* This method applies a colormap to the specified value an mixes it with the specified color. It uses the proper colormap and is able to
* unscale values if needed. It uses real compositing.
*
* \param color this color gets mixed using alpha value with the new colormap color
* \param sampler the texture sampler to use
......@@ -48,9 +48,18 @@
void colormap( inout vec4 color, in sampler3D sampler, in vec3 coord, float minV, float scaleV, float thresholdV, float alpha, int cmap,
bool active )
{
// get the value
vec4 value = texture3D( sampler, coord );
colormap( color, value, minV, scaleV, thresholdV, alpha, cmap, active );
// get the value and descale it
vec3 value = texture3D( sampler, coord ).rgb;
// let someone else apply the colormap
vec4 src = colormap( value, minV, scaleV, thresholdV, alpha, cmap, active );
// compositing:
// associated colors needed
src.rgb *= src.a;
//src.a = 1.0;
// apply front-to-back compositing
color = ( 1.0 - color.a ) * src + color;
}
/**
......@@ -65,7 +74,7 @@ void colormap( inout vec4 color, in sampler3D sampler, in vec3 coord, float minV
*/
vec4 colormapping( vec4 texcoord )
{
vec4 finalColor = vec4( 0.0, 0.0, 0.0, 1.0 );
vec4 finalColor = vec4( 0.0, 0.0, 0.0, 0.0 );
// ColormapPreTransform is a mat4 defined by OpenWalnut before compilation
vec4 t = ColormapPreTransform * texcoord;
......@@ -125,7 +134,7 @@ vec4 colormapping( vec4 texcoord )
*/
vec4 colormapping()
{
vec4 finalColor = vec4( 0.0, 0.0, 0.0, 1.0 );
vec4 finalColor = vec4( 0.0, 0.0, 0.0, 0.0 );
// back to front compositing
#ifdef Colormap7Enabled
......
......@@ -31,6 +31,7 @@
#include "../../graphicsEngine/WGEGeodeUtils.h"
#include "../../graphicsEngine/callbacks/WGELinearTranslationCallback.h"
#include "../../graphicsEngine/callbacks/WGENodeMaskCallback.h"
#include "../../graphicsEngine/callbacks/WGEShaderAnimationCallback.h"
#include "../../graphicsEngine/shaders/WGEPropertyUniform.h"
#include "../../graphicsEngine/shaders/WGEShader.h"
#include "../../graphicsEngine/shaders/WGEShaderDefineOptions.h"
......@@ -212,6 +213,15 @@ void WMNavigationSlices::initOSG()
// Done
///////////////////////////////////////////////////////////////////////////////////////////////
osg::ref_ptr< osg::StateSet > state = m_output->getOrCreateStateSet();
state->setMode( GL_BLEND, osg::StateAttribute::ON );
state->setRenderingHint( osg::StateSet::TRANSPARENT_BIN );
// we want some nice animations: add timer
osg::ref_ptr< osg::Uniform > animationUniform = new osg::Uniform( "u_timer", 0 );
state->addUniform( animationUniform );
animationUniform->setUpdateCallback( new WGEShaderAnimationCallback() );
// add the transformation nodes to the output group
m_output->insert( mX );
m_output->insert( mY );
......@@ -222,12 +232,14 @@ void WMNavigationSlices::initOSG()
WMNavigationSlices::PickCallback::PickCallback( osg::ref_ptr< osg::Node > node, WPropDouble property, bool negateDirection ):
m_node( node ),
m_property( property ),
m_pickUniform( new osg::Uniform( "u_picked", 0.0f ) ),
m_dir( negateDirection ? -1.0 : 1.0 )
{
boost::shared_ptr< WGraphicsEngine > ge = WGraphicsEngine::getGraphicsEngine();
boost::shared_ptr< WGEViewer > viewer = ge->getViewerByName( "main" );
m_camera = viewer->getCamera();
m_pickConnection = viewer->getPickHandler()->getPickSignal()->connect( boost::bind( &WMNavigationSlices::PickCallback::pick, this, _1 ) );
node->getOrCreateStateSet()->addUniform( m_pickUniform );
}
void WMNavigationSlices::PickCallback::pick( WPickInfo pickInfo )
......@@ -253,10 +265,12 @@ void WMNavigationSlices::PickCallback::pick( WPickInfo pickInfo )
// this might have initialized dragging. Keep track of old position
m_oldPixelPosition = newPixelPos;
m_isPicked = true;
m_pickUniform->set( 1.0f );
}
else // someone else got picked.
{
m_isPicked = false;
m_pickUniform->set( 0.0f );
}
}
......
......@@ -160,6 +160,11 @@ private:
*/
bool m_isPicked;
/**
* This uniform is used to inform the shader about current pick-state
*/
osg::ref_ptr< osg::Uniform > m_pickUniform;
/**
* The stored pixel position of a previous drag event.
*/
......
......@@ -26,12 +26,30 @@
#include "WGEColormapping-fragment.glsl"
// this color is used if currently picking the slice
const vec4 pickColor = vec4( 0.25, 0.0, 0.75, 1.0 );
// if this is 1, the slice is currently in pick mode
uniform float u_picked;
// animation time. Used for pick-animation
uniform int u_timer;
/**
* Applies colormapping.
*/
void main()
{
// get the colormap
vec4 cmap = colormapping();
gl_FragColor = cmap;
// this creates a sinuidal blending in [0,1] with one complete 2pi cycle per second
// NOTE: the 100.0 depends on the timer tick. We have a timer that counts one per a hundreth of a second.
float pickColorIntensity = 0.5 * ( 1.0 + sin( 3.0 * 3.1472 * float( u_timer ) / 100.0 ) );
// as we use this for blending, we want it to swing in [0.5-0.75]
pickColorIntensity = 0.5 + ( pickColorIntensity * 0.25 );
// mix colormapping and pick color
gl_FragColor = mix( pickColor, cmap, ( ( 1.0 - u_picked ) * 1.0 ) + ( u_picked * pickColorIntensity ) );
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment