Commit 301aec7e authored by Sebastian Eichelbaum's avatar Sebastian Eichelbaum
Browse files

[CHANGE] - cleaned up shader code

[ADD] - added some uniforms/properties
[ADD] - initial particle distribution is now generated
parent bc7af9cf
......@@ -104,13 +104,8 @@ void WMSurfaceParticles::properties()
// Initialize the properties
m_propCondition = boost::shared_ptr< WCondition >( new WCondition() );
m_isoSurface = m_properties2->addProperty( "Isosurface Mode", "If enabled, the Volume Renderer will render an isosurface and ignores the"
"transfer function.", true );
m_isoValue = m_properties2->addProperty( "Isovalue", "The Isovalue used whenever the Isosurface Mode is turned on.",
50 );
m_isoColor = m_properties2->addProperty( "Iso Color", "The color to blend the isosurface with.", WColor( 1.0, 1.0, 1.0, 1.0 ),
m_propCondition );
m_stepCount = m_properties2->addProperty( "Step Count", "The number of steps to walk along the ray during raycasting. A low value"
"may cause artifacts whilst a high value slows down rendering.", 250 );
m_stepCount->setMin( 1 );
......@@ -118,7 +113,13 @@ void WMSurfaceParticles::properties()
m_alpha = m_properties2->addProperty( "Opacity %", "The opacity in %. Transparency = 100 - Opacity.", 100 );
m_useSimpleDepthColoring = m_properties2->addProperty( "Use Depth Cueing", "Enable it to have simple depth dependent coloring only.", false );
m_gridResolution = m_properties2->addProperty( "Grid Resolution",
"Determines the grid resolution for the particles in relation to the dataset grid.", 25.0
);
m_particleSize = m_properties2->addProperty( "Particle Size", "The size of a particle in relation to the voxel.", 1.0 );
m_particleSize->setMin( 0 );
m_particleSize->setMax( 100 );
}
void WMSurfaceParticles::moduleMain()
......@@ -152,13 +153,6 @@ void WMSurfaceParticles::moduleMain()
bool dataChanged = ( m_dataSet != newDataSet ) || ( m_directionDataSet != newDirectionDataSet );
bool dataValid = ( newDataSet && newDirectionDataSet );
// m_isoColor changed
if ( m_isoColor->changed() )
{
// a new color requires the proxy geometry to be rebuild as we store it as color in this geometry
dataChanged = true;
}
// As the data has changed, we need to recreate the texture.
if ( dataChanged && dataValid )
{
......@@ -179,7 +173,7 @@ void WMSurfaceParticles::moduleMain()
std::pair< wmath::WPosition, wmath::WPosition > bb = grid->getBoundingBox();
// use the OSG Shapes, create unit cube
osg::ref_ptr< osg::Node > cube = wge::generateSolidBoundingBoxNode( bb.first, bb.second, m_isoColor->get( true ) );
osg::ref_ptr< osg::Node > cube = wge::generateSolidBoundingBoxNode( bb.first, bb.second, WColor( 0.0, 0.0, 0.0, 1.0 ) );
cube->asTransform()->getChild( 0 )->setName( "DVR Proxy Cube" ); // Be aware that this name is used in the pick handler.
m_shader->apply( cube );
......@@ -209,23 +203,23 @@ void WMSurfaceParticles::moduleMain()
osg::ref_ptr< osg::Uniform > isovalue = new osg::Uniform( "u_isovalue", static_cast< float >( m_isoValue->get() / 100.0 ) );
isovalue->setUpdateCallback( new SafeUniformCallback( this ) );
osg::ref_ptr< osg::Uniform > isosurface = new osg::Uniform( "u_isosurface", m_isoSurface->get() );
isosurface->setUpdateCallback( new SafeUniformCallback( this ) );
osg::ref_ptr< osg::Uniform > steps = new osg::Uniform( "u_steps", m_stepCount->get() );
steps->setUpdateCallback( new SafeUniformCallback( this ) );
osg::ref_ptr< osg::Uniform > alpha = new osg::Uniform( "u_alpha", static_cast< float >( m_alpha->get() / 100.0 ) );
alpha->setUpdateCallback( new SafeUniformCallback( this ) );
osg::ref_ptr< osg::Uniform > depthCueingOnly = new osg::Uniform( "u_depthCueingOnly", m_useSimpleDepthColoring->get() );
depthCueingOnly->setUpdateCallback( new SafeUniformCallback( this ) );
osg::ref_ptr< osg::Uniform > gridResolution = new osg::Uniform( "u_gridResolution", static_cast< float >( m_gridResolution->get() ) );
gridResolution->setUpdateCallback( new SafeUniformCallback( this ) );
osg::ref_ptr< osg::Uniform > particleSize = new osg::Uniform( "u_particleSize", static_cast< float >( m_particleSize->get() ) );
particleSize->setUpdateCallback( new SafeUniformCallback( this ) );
rootState->addUniform( isovalue );
rootState->addUniform( isosurface );
rootState->addUniform( steps );
rootState->addUniform( alpha );
rootState->addUniform( depthCueingOnly );
rootState->addUniform( gridResolution );
rootState->addUniform( particleSize );
// update node
WKernel::getRunningKernel()->getGraphicsEngine()->getScene()->remove( m_rootNode );
......@@ -254,10 +248,6 @@ void WMSurfaceParticles::SafeUniformCallback::operator()( osg::Uniform* uniform,
{
uniform->set( static_cast< float >( m_module->m_isoValue->get( true ) / 100.0 ) );
}
if ( m_module->m_isoSurface->changed() && ( uniform->getName() == "u_isosurface" ) )
{
uniform->set( m_module->m_isoSurface->get( true ) );
}
if ( m_module->m_stepCount->changed() && ( uniform->getName() == "u_steps" ) )
{
uniform->set( m_module->m_stepCount->get( true ) );
......@@ -266,9 +256,13 @@ void WMSurfaceParticles::SafeUniformCallback::operator()( osg::Uniform* uniform,
{
uniform->set( static_cast< float >( m_module->m_alpha->get( true ) / 100.0 ) );
}
if ( m_module->m_useSimpleDepthColoring->changed() && ( uniform->getName() == "u_depthCueingOnly" ) )
if ( m_module->m_gridResolution->changed() && ( uniform->getName() == "u_gridResolution" ) )
{
uniform->set( static_cast< float >( m_module->m_gridResolution->get( true ) ) );
}
if ( m_module->m_particleSize->changed() && ( uniform->getName() == "u_particleSize" ) )
{
uniform->set( m_module->m_useSimpleDepthColoring->get( true ) );
uniform->set( static_cast< float >( m_module->m_particleSize->get( true ) ) );
}
}
......
......@@ -94,11 +94,6 @@ protected:
*/
virtual void properties();
/**
* The root node used for this modules graphics. For OSG nodes, always use osg::ref_ptr to ensure proper resource management.
*/
osg::ref_ptr< osg::Node > m_rootNode;
/**
* Callback for m_active. Overwrite this in your modules to handle m_active changes separately.
*/
......@@ -126,21 +121,15 @@ private:
*/
boost::shared_ptr< WDataSetSingle > m_directionDataSet;
/**
* If this property is true, as special shader is used which emulates isosurfaces using the m_isoValue property.
*/
WPropBool m_isoSurface;
/////////////////////////////////////////////////////////////////////
// The Properties
/////////////////////////////////////////////////////////////////////
/**
* The Isovalue used in the case m_isoSurface is true.
*/
WPropInt m_isoValue;
/**
* The color used when in isosurface mode for blending.
*/
WPropColor m_isoColor;
/**
* The number of steps to walk along the ray.
*/
......@@ -152,15 +141,29 @@ private:
WPropInt m_alpha;
/**
* If true, the shader will only color using the depth of the point on the surface.
* Determines the grid resolution in relation to the dataset grid.
*/
WPropBool m_useSimpleDepthColoring;
WPropDouble m_gridResolution;
/**
* The size of a particle in relation to the voxel
*/
WPropDouble m_particleSize;
/**
* A condition used to notify about changes in several properties.
*/
boost::shared_ptr< WCondition > m_propCondition;
/////////////////////////////////////////////////////////////////////
// OSG Stuff
/////////////////////////////////////////////////////////////////////
/**
* The root node used for this modules graphics. For OSG nodes, always use osg::ref_ptr to ensure proper resource management.
*/
osg::ref_ptr< osg::Node > m_rootNode;
/**
* the DVR shader.
*/
......
......@@ -24,15 +24,19 @@
#version 120
/////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////
// Varyings
/////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////
#include "GPUSurfaceParticles.varyings"
/////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////
// Uniforms
/////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////
// **************************************************************************
// Uniforms defining the input textures
// **************************************************************************
// texture containing the data
uniform sampler3D tex0;
......@@ -49,33 +53,49 @@ uniform float u_tex1Min;
// texture containing the directional data -> the max value of the values in the texture
uniform float u_tex1Max;
// **************************************************************************
// Uniforms for the isosurface mode
// **************************************************************************
// The isovalue to use.
uniform float u_isovalue;
// Should the shader create some kind of isosurface instead of a volume rendering?
uniform bool u_isosurface;
// True if only the simple depth value should be used for coloring
uniform bool u_depthCueingOnly;
// The number of steps to use.
uniform int u_steps;
// The alpha value to set
uniform float u_alpha;
/////////////////////////////////////////////////////////////////////////////
// **************************************************************************
// Uniforms defining the initial particle distribution
// **************************************************************************
// Uniform defining the grid resolution scaling in relation to the dataset grid
uniform float u_gridResolution;
// Relative size of the particle to the voxel
uniform float u_particleSize;
///////////////////////////////////////////////////////////////////////////////////////////////////
// Attributes
/////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////
// Variables
/////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////
// Functions
/////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Calculates the endpoint and distance using the ray and ray-start-point up to the end of the
* bounding volume.
*
* \param d the distance along the ray until the ray leaves the bounding volume.
*
* \return the end point -> v_rayStart + v_ray*d
*/
vec3 findRayEnd( out float d )
{
vec3 r = v_ray + vec3( 0.0000001 );
......@@ -130,7 +150,7 @@ vec3 getDirection( vec3 point )
void main()
{
// please do not laugh, it is a very very very simple "isosurface" shader
gl_FragColor = vec4( 1.0, 0.0, 0.0, 1.0 );
vec4 color = vec4( 1.0, 0.0, 0.0, 1.0 );
gl_FragDepth = gl_FragCoord.z;
// First, find the rayEnd point. We need to do it in the fragment shader as the ray end point may be interpolated wrong
......@@ -138,87 +158,78 @@ void main()
float totalDistance = 0.0;
vec3 rayEnd = findRayEnd( totalDistance );
// Isosurface Mode
if ( u_isosurface )
{
// the point along the ray in cube coordinates
vec3 curPoint = v_rayStart;
// the point along the ray in cube coordinates
vec3 curPoint = v_rayStart;
// the current value inside the data
float value;
// the current value inside the data
float value;
// the step counter
int i = 0;
float stepDistance = totalDistance / float( u_steps );
while ( i < u_steps ) // we do not need to ch
// the step counter
int i = 0;
float stepDistance = totalDistance / float( u_steps );
while ( i < u_steps ) // we do not need to ch
{
// get current value
value = texture3D( tex0, curPoint ).r;
// is it the isovalue?
if ( abs( value - u_isovalue ) < 0.1 )
{
// get current value
value = texture3D( tex0, curPoint ).r;
// is it the isovalue?
if ( abs( value - u_isovalue ) < 0.1 )
{
// we need to know the depth value of the current point inside the cube
// Therefore, the complete standard pipeline is reproduced here:
// 1: transfer to world space and right after it, to eye space
vec4 curPointProjected = gl_ModelViewProjectionMatrix * vec4( curPoint, 1.0 );
// 2: scale to screen space and [0,1]
// -> x and y is not needed
// curPointProjected.x /= curPointProjected.w;
// curPointProjected.x = curPointProjected.x * 0.5 + 0.5 ;
// curPointProjected.y /= curPointProjected.w;
// curPointProjected.y = curPointProjected.y * 0.5 + 0.5 ;
curPointProjected.z /= curPointProjected.w;
curPointProjected.z = curPointProjected.z * 0.5 + 0.5 ;
// 3: set depth value
gl_FragDepth = curPointProjected.z;
// 4: set color
vec4 color;
if ( u_depthCueingOnly )
{
float d = 1.0 - curPointProjected.z;
color = gl_Color * 1.5 * d * d;
color = vec4( getDirection( curPoint ), 1.0 );
}
else
{
// NOTE: these are a lot of weird experiments ;-)
float d = 1.0 - curPointProjected.z;
d = 1.5*pointDistance( curPoint, vec3( 0.5 ) );
float w = dot( normalize( vec3( 0.5 ) - curPoint ), normalize( v_ray ) );
w = ( w + 0.5 );
if ( w > 0.8 ) w = 0.8;
float d2 = w*d*d*d*d*d;
color = gl_Color * 11.0 * d2;
}
color.a = u_alpha;
gl_FragColor = color;
break;
}
else
{
// no it is not the iso value
// -> continue along the ray
curPoint += stepDistance * v_ray;
}
// do not miss to count the steps already done
i++;
// we need to know the depth value of the current point inside the cube
// Therefore, the complete standard pipeline is reproduced here:
// 1: transfer to world space and right after it, to eye space
vec4 curPointProjected = gl_ModelViewProjectionMatrix * vec4( curPoint, 1.0 );
// 2: scale to screen space and [0,1]
// -> x and y is not needed
// curPointProjected.x /= curPointProjected.w;
// curPointProjected.x = curPointProjected.x * 0.5 + 0.5 ;
// curPointProjected.y /= curPointProjected.w;
// curPointProjected.y = curPointProjected.y * 0.5 + 0.5 ;
curPointProjected.z /= curPointProjected.w;
curPointProjected.z = curPointProjected.z * 0.5 + 0.5 ;
// 3: set depth value
gl_FragDepth = curPointProjected.z;
// 4: set colors/ ooutput to textures
// The values need to be transferred to the next (image space based) steps.
// the current point is now relating to the coordinate system, which is in { (x,y,z) | x in [-1,1], y in [-1,1] and z in [-1,1] }
// (the texture coordinate system). We increase the resolution by scaling the point:
curPoint *= u_gridResolution;
// each point can than be defined as offset to a voxels root coordinate:
vec3 rasterPoint = curPoint - floor( curPoint );
rasterPoint -= vec3( 0.5, 0.5, 0.5 );
// the raster point is then, for each voxel in { (x,y,z) | x in [-1,1], y in [-1,1] and z in [-1,1] }, interpreted as sphere surface:
float sphere = ( rasterPoint.x * rasterPoint.x + rasterPoint.y * rasterPoint.y ) * 4.0 * u_particleSize;
color = vec4( 1.0-sphere, 0.0, 0.0, 1.0);
break;
}
// the ray did never hit the surface --> discard the pixel
if ( i == u_steps )
else
{
discard;
// no it is not the iso value
// -> continue along the ray
curPoint += stepDistance * v_ray;
}
// do not miss to count the steps already done
i++;
}
// the ray did never hit the surface --> discard the pixel
if ( i == u_steps )
{
discard;
}
// set the color
color.a = u_alpha;
gl_FragColor = color;
}
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