2012-05-18 09:45:23 +02:00
//##################################################################################################
//
// Custom Visualization Core library
2013-09-20 15:22:29 +02:00
// Copyright (C) 2011-2013 Ceetron AS
//
// This library may be used under the terms of either the GNU General Public License or
// the GNU Lesser General Public License as follows:
//
// GNU General Public License Usage
// This library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This library 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 General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
// GNU Lesser General Public License Usage
// This library 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 2.1 of the License, or
// (at your option) any later version.
//
// This library 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 at <<http://www.gnu.org/licenses/lgpl-2.1.html>>
// for more details.
2012-05-18 09:45:23 +02:00
//
//##################################################################################################
2013-09-20 15:22:29 +02:00
2012-05-18 09:45:23 +02:00
#include "cafEffectGenerator.h"
#include "cafUtils.h"
#include "cvfRenderState_FF.h"
#include "cvfTextureImage.h"
#include "cvfTexture2D_FF.h"
#include "cvfShaderProgramGenerator.h"
#include "cvfShaderSourceProvider.h"
#include "cvfUniform.h"
#include "cvfShaderProgram.h"
#include "cvfMatrixState.h"
#include "cvfTexture.h"
#include "cvfSampler.h"
2012-10-02 10:17:52 +02:00
#include "cvfRenderStatePolygonOffset.h"
#include "cvfRenderStateBlending.h"
#include "cvfRenderStateCullFace.h"
#include "cvfRenderStateTextureBindings.h"
#include "cvfRenderStatePolygonMode.h"
#include "cvfRenderStateDepth.h"
2012-05-18 09:45:23 +02:00
#include <QtOpenGL/QGLFormat>
2012-08-31 19:12:47 +02:00
#include "cafEffectCache.h"
2012-05-18 09:45:23 +02:00
namespace caf {
2013-09-20 13:56:24 +02:00
//=============================================================================================================================
//=============================================================================================================================
2012-10-02 10:17:52 +02:00
static const char light_AmbientDiffuse_inl [] =
" \n "
"varying vec3 v_ecPosition; \n "
"varying vec3 v_ecNormal; \n "
2016-08-16 10:58:07 +02:00
"uniform vec3 u_ecLightPosition; \n "
2012-10-02 10:17:52 +02:00
" \n "
"//-------------------------------------------------------------------------------------------------- \n "
2016-08-16 10:58:07 +02:00
"/// lightFragment() - Simple Positional Headlight without Phong/specular component \n "
2012-10-02 10:17:52 +02:00
"/// \n "
"//-------------------------------------------------------------------------------------------------- \n "
"vec4 lightFragment(vec4 srcFragColor, float not_in_use_shadowFactor) \n "
"{ \n "
" const float ambientIntensity = 0.2; \n "
" \n "
" // Light vector (from point to light source) \n "
2016-08-16 10:58:07 +02:00
" vec3 L = normalize(u_ecLightPosition - v_ecPosition); \n "
2012-10-02 10:17:52 +02:00
" \n "
" // Viewing vector (from point to eye) \n "
" // Since we are in eye space, the eye pos is at (0, 0, 0) \n "
" vec3 V = normalize(-v_ecPosition); \n "
" \n "
" vec3 N = normalize(v_ecNormal); \n "
" vec3 R = normalize(reflect(-L, N)); \n "
" \n "
" vec3 ambient = srcFragColor.rgb*ambientIntensity; \n "
" vec3 diffuse = srcFragColor.rgb*(1.0 - ambientIntensity)*abs(dot(N, L)); \n "
" \n "
" return vec4(ambient + diffuse, srcFragColor.a); \n "
"} \n " ;
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvf :: String CommonShaderSources :: light_AmbientDiffuse ()
{
return cvf :: String ( light_AmbientDiffuse_inl );
}
2013-12-17 13:11:46 +01:00
//--------------------------------------------------------------------------------------------------
/// Static helper to configure polygon offset render state from enum
//--------------------------------------------------------------------------------------------------
2014-04-08 08:37:22 +02:00
cvf :: ref < cvf :: RenderStatePolygonOffset > EffectGenerator :: createAndConfigurePolygonOffsetRenderState ( PolygonOffset polygonOffset )
2013-12-17 13:11:46 +01:00
{
cvf :: ref < cvf :: RenderStatePolygonOffset > rs = new cvf :: RenderStatePolygonOffset ;
if ( polygonOffset == PO_NONE )
{
return rs ;
}
rs -> enableFillMode ( true );
2013-12-18 12:13:44 +01:00
2013-12-17 13:11:46 +01:00
switch ( polygonOffset )
{
2013-12-18 12:13:44 +01:00
case PO_1 : rs -> setFactor ( 1.0f ); rs -> setUnits ( 1.0f ); break ;
case PO_2 : rs -> setFactor ( 2.0f ); rs -> setUnits ( 2.0f ); break ;
case PO_NEG_LARGE : rs -> setFactor ( - 1.0f ); rs -> setUnits ( - 30.0f ); break ;
2013-12-17 13:11:46 +01:00
default :
CVF_FAIL_MSG ( "Unhandled polygon offset enum" );
}
return rs ;
}
2012-05-18 09:45:23 +02:00
//==================================================================================================
//
// EffectGenerator Base class
//
//==================================================================================================
EffectGenerator :: RenderingModeType EffectGenerator :: sm_renderingMode = SHADER_BASED ;
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void EffectGenerator :: setRenderingMode ( RenderingModeType effectType )
{
sm_renderingMode = effectType ;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
EffectGenerator :: RenderingModeType EffectGenerator :: renderingMode ()
{
return sm_renderingMode ;
}
//--------------------------------------------------------------------------------------------------
2015-07-29 14:19:43 +02:00
///
2012-05-18 09:45:23 +02:00
//--------------------------------------------------------------------------------------------------
2015-08-13 14:35:30 +02:00
cvf :: ref < cvf :: Effect > EffectGenerator :: generateCachedEffect () const
2012-05-18 09:45:23 +02:00
{
2012-08-31 19:12:47 +02:00
cvf :: ref < cvf :: Effect > eff = caf :: EffectCache :: instance () -> findEffect ( this );
2015-07-29 14:19:43 +02:00
if ( eff . notNull ()) return eff . p ();
2012-08-31 19:12:47 +02:00
2015-08-13 14:35:30 +02:00
eff = generateUnCachedEffect ();
2015-07-29 14:19:43 +02:00
caf :: EffectCache :: instance () -> addEffect ( this , eff . p ());
return eff ;
}
//--------------------------------------------------------------------------------------------------
/// Creates a new effect using the settings in the inherited generator.
/// Creates a new effect and calls the correct update-Effect method dep. on the effect type (software/shader)
//--------------------------------------------------------------------------------------------------
2015-08-13 14:35:30 +02:00
cvf :: ref < cvf :: Effect > EffectGenerator :: generateUnCachedEffect () const
2015-07-29 14:19:43 +02:00
{
cvf :: ref < cvf :: Effect > eff = new cvf :: Effect ;
2012-08-31 19:12:47 +02:00
2012-05-18 09:45:23 +02:00
if ( sm_renderingMode == SHADER_BASED )
{
updateForShaderBasedRendering ( eff . p ());
}
else
{
updateForFixedFunctionRendering ( eff . p ());
}
return eff ;
}
2015-07-29 14:19:43 +02:00
2012-05-18 09:45:23 +02:00
//--------------------------------------------------------------------------------------------------
/// Updates the effect to the state defined by the inherited effect generator.
/// This can be used to update an effect used several places in the scene.
/// Will first reset the effect, and then call the correct updateEffect method implemented in the inherited generator.
//--------------------------------------------------------------------------------------------------
void EffectGenerator :: updateEffect ( cvf :: Effect * effect ) const
{
CVF_ASSERT ( effect != NULL );
// Clear effect
effect -> setRenderStateSet ( NULL );
effect -> setUniformSet ( NULL );
effect -> setShaderProgram ( NULL );
if ( sm_renderingMode == SHADER_BASED )
{
updateForShaderBasedRendering ( effect );
}
else
{
updateForFixedFunctionRendering ( effect );
}
}
2012-08-31 19:12:47 +02:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void EffectGenerator :: clearEffectCache ()
{
EffectCache :: instance () -> clear ();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void EffectGenerator :: releaseUnreferencedEffects ()
{
EffectCache :: instance () -> releaseUnreferencedEffects ();
}
2012-05-18 09:45:23 +02:00
//==================================================================================================
//
// SurfaceEffectGenerator
//
//==================================================================================================
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2013-12-17 13:11:46 +01:00
SurfaceEffectGenerator :: SurfaceEffectGenerator ( const cvf :: Color4f & color , PolygonOffset polygonOffset )
2012-05-18 09:45:23 +02:00
{
m_color = color ;
m_polygonOffset = polygonOffset ;
2013-12-18 08:57:10 +01:00
m_cullBackfaces = FC_NONE ;
2013-12-18 12:13:44 +01:00
m_enableDepthWrite = true ;
2015-10-23 09:34:47 +02:00
m_enableLighting = true ;
2012-05-18 09:45:23 +02:00
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2013-12-17 13:11:46 +01:00
SurfaceEffectGenerator :: SurfaceEffectGenerator ( const cvf :: Color3f & color , PolygonOffset polygonOffset )
2012-05-18 09:45:23 +02:00
{
m_color = cvf :: Color4f ( color , 1.0f );
m_polygonOffset = polygonOffset ;
2013-12-18 08:57:10 +01:00
m_cullBackfaces = FC_NONE ;
2013-12-18 12:13:44 +01:00
m_enableDepthWrite = true ;
2015-10-23 09:34:47 +02:00
m_enableLighting = true ;
2012-05-18 09:45:23 +02:00
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void SurfaceEffectGenerator :: updateForShaderBasedRendering ( cvf :: Effect * effect ) const
{
cvf :: ShaderProgramGenerator gen ( "SurfaceEffectGenerator" , cvf :: ShaderSourceProvider :: instance ());
gen . addVertexCode ( cvf :: ShaderSourceRepository :: vs_Standard );
gen . addFragmentCode ( cvf :: ShaderSourceRepository :: src_Color );
2015-10-23 09:34:47 +02:00
if ( m_enableLighting )
{
gen . addFragmentCode ( CommonShaderSources :: light_AmbientDiffuse ());
gen . addFragmentCode ( cvf :: ShaderSourceRepository :: fs_Standard );
}
else
{
gen . addFragmentCode ( cvf :: ShaderSourceRepository :: fs_Unlit );
}
2012-05-18 09:45:23 +02:00
cvf :: ref < cvf :: ShaderProgram > shaderProg = gen . generate ();
2016-08-16 10:58:07 +02:00
if ( m_enableLighting ) shaderProg -> setDefaultUniform ( new cvf :: UniformFloat ( "u_ecLightPosition" , cvf :: Vec3f ( 0.5 , 5.0 , 7.0 )));
2012-05-18 09:45:23 +02:00
cvf :: ref < cvf :: Effect > eff = effect ;
eff -> setShaderProgram ( shaderProg . p ());
eff -> setUniform ( new cvf :: UniformFloat ( "u_color" , m_color ));
2016-08-16 10:58:07 +02:00
2012-05-18 09:45:23 +02:00
this -> updateCommonEffect ( effect );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void SurfaceEffectGenerator :: updateForFixedFunctionRendering ( cvf :: Effect * effect ) const
{
cvf :: ref < cvf :: Effect > eff = effect ;
2012-10-02 10:17:52 +02:00
cvf :: ref < cvf :: RenderStateMaterial_FF > mat = new cvf :: RenderStateMaterial_FF ( m_color . toColor3f ());
2012-05-18 09:45:23 +02:00
mat -> setAlpha ( m_color . a ());
eff -> setRenderState ( mat . p ());
2012-10-02 10:17:52 +02:00
cvf :: ref < cvf :: RenderStateLighting_FF > lighting = new cvf :: RenderStateLighting_FF ;
2012-05-18 09:45:23 +02:00
lighting -> enableTwoSided ( true );
2015-10-23 09:34:47 +02:00
lighting -> enable ( m_enableLighting );
2012-05-18 09:45:23 +02:00
eff -> setRenderState ( lighting . p ());
this -> updateCommonEffect ( effect );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void SurfaceEffectGenerator :: updateCommonEffect ( cvf :: Effect * effect ) const
{
2013-12-17 13:11:46 +01:00
if ( m_polygonOffset != PO_NONE )
2012-05-18 09:45:23 +02:00
{
2014-04-08 08:37:22 +02:00
cvf :: ref < cvf :: RenderStatePolygonOffset > polyOffset = EffectGenerator :: createAndConfigurePolygonOffsetRenderState ( m_polygonOffset );
2012-05-18 09:45:23 +02:00
effect -> setRenderState ( polyOffset . p ());
}
// Simple transparency
if ( m_color . a () < 1.0f )
{
2012-10-02 10:17:52 +02:00
cvf :: ref < cvf :: RenderStateBlending > blender = new cvf :: RenderStateBlending ;
2012-05-18 09:45:23 +02:00
blender -> configureTransparencyBlending ();
effect -> setRenderState ( blender . p ());
}
2013-12-18 13:21:03 +01:00
// Face culling
2013-12-18 08:57:10 +01:00
if ( m_cullBackfaces != FC_NONE )
2012-05-18 09:45:23 +02:00
{
2012-10-02 10:17:52 +02:00
cvf :: ref < cvf :: RenderStateCullFace > faceCulling = new cvf :: RenderStateCullFace ;
2013-12-18 08:57:10 +01:00
if ( m_cullBackfaces == FC_BACK )
{
faceCulling -> setMode ( cvf :: RenderStateCullFace :: BACK );
}
else if ( m_cullBackfaces == FC_FRONT )
{
faceCulling -> setMode ( cvf :: RenderStateCullFace :: FRONT );
}
else if ( m_cullBackfaces == FC_FRONT_AND_BACK )
{
faceCulling -> setMode ( cvf :: RenderStateCullFace :: FRONT_AND_BACK );
}
2012-05-18 09:45:23 +02:00
effect -> setRenderState ( faceCulling . p ());
}
2013-12-18 12:13:44 +01:00
if ( ! m_enableDepthWrite )
{
cvf :: ref < cvf :: RenderStateDepth > depth = new cvf :: RenderStateDepth ;
depth -> enableDepthWrite ( false );
effect -> setRenderState ( depth . p ());
}
2012-05-18 09:45:23 +02:00
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool SurfaceEffectGenerator :: isEqual ( const EffectGenerator * other ) const
{
const SurfaceEffectGenerator * otherSurfaceEffect = dynamic_cast < const SurfaceEffectGenerator *> ( other );
if ( otherSurfaceEffect )
{
if ( m_color == otherSurfaceEffect -> m_color
&& m_polygonOffset == otherSurfaceEffect -> m_polygonOffset
2013-12-18 12:13:44 +01:00
&& m_enableDepthWrite == otherSurfaceEffect -> m_enableDepthWrite
2015-10-23 09:34:47 +02:00
&& m_enableLighting == otherSurfaceEffect -> m_enableLighting
2012-05-18 09:45:23 +02:00
&& m_cullBackfaces == otherSurfaceEffect -> m_cullBackfaces )
{
return true ;
}
}
return false ;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
EffectGenerator * SurfaceEffectGenerator :: copy () const
{
SurfaceEffectGenerator * effGen = new SurfaceEffectGenerator ( m_color , m_polygonOffset );
effGen -> m_cullBackfaces = m_cullBackfaces ;
2013-12-18 12:13:44 +01:00
effGen -> m_enableDepthWrite = m_enableDepthWrite ;
2015-10-23 09:34:47 +02:00
effGen -> m_enableLighting = m_enableLighting ;
2012-05-18 09:45:23 +02:00
return effGen ;
}
//==================================================================================================
//
// ScalarMapperEffectGenerator
//
//==================================================================================================
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2013-12-17 13:11:46 +01:00
ScalarMapperEffectGenerator :: ScalarMapperEffectGenerator ( const cvf :: ScalarMapper * scalarMapper , PolygonOffset polygonOffset )
2012-05-18 09:45:23 +02:00
: m_undefinedColor ( cvf :: Color3 :: GRAY )
{
m_scalarMapper = scalarMapper ;
m_polygonOffset = polygonOffset ;
m_opacityLevel = 1.0f ;
2013-12-18 13:53:32 +01:00
m_faceCulling = FC_NONE ;
2013-12-19 08:59:28 +01:00
m_enableDepthWrite = true ;
2015-06-17 15:00:20 +02:00
m_disableLighting = false ;
2012-05-18 09:45:23 +02:00
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void ScalarMapperEffectGenerator :: updateForShaderBasedRendering ( cvf :: Effect * effect ) const
{
cvf :: ref < cvf :: Effect > eff = effect ;
cvf :: ShaderProgramGenerator gen ( "ScalarMapperEffectGenerator" , cvf :: ShaderSourceProvider :: instance ());
gen . addVertexCode ( cvf :: ShaderSourceRepository :: vs_Standard );
gen . addFragmentCode ( cvf :: ShaderSourceRepository :: src_Texture );
2015-06-17 15:00:20 +02:00
if ( m_disableLighting )
{
gen . addFragmentCode ( cvf :: ShaderSourceRepository :: fs_Unlit );
}
else
{
gen . addFragmentCode ( CommonShaderSources :: light_AmbientDiffuse ());
gen . addFragmentCode ( cvf :: ShaderSourceRepository :: fs_Standard );
}
2012-05-18 09:45:23 +02:00
cvf :: ref < cvf :: ShaderProgram > prog = gen . generate ();
eff -> setShaderProgram ( prog . p ());
2016-08-16 10:58:07 +02:00
if ( ! m_disableLighting ) prog -> setDefaultUniform ( new cvf :: UniformFloat ( "u_ecLightPosition" , cvf :: Vec3f ( 0.5 , 5.0 , 7.0 )));
2012-05-18 09:45:23 +02:00
// Result mapping texture
2012-08-31 19:12:47 +02:00
m_textureImage = new cvf :: TextureImage ();
m_scalarMapper -> updateTexture ( m_textureImage . p ());
2012-05-18 09:45:23 +02:00
2012-08-31 19:12:47 +02:00
cvf :: ref < cvf :: TextureImage > modTexImg = ScalarMapperEffectGenerator :: addAlphaAndUndefStripes ( m_textureImage . p (), m_undefinedColor , m_opacityLevel );
2012-05-18 09:45:23 +02:00
cvf :: ref < cvf :: Texture > texture = new cvf :: Texture ( modTexImg . p ());
cvf :: ref < cvf :: Sampler > sampler = new cvf :: Sampler ;
sampler -> setWrapMode ( cvf :: Sampler :: CLAMP_TO_EDGE );
sampler -> setMinFilter ( cvf :: Sampler :: NEAREST );
sampler -> setMagFilter ( cvf :: Sampler :: NEAREST );
2012-10-02 10:17:52 +02:00
cvf :: ref < cvf :: RenderStateTextureBindings > texBind = new cvf :: RenderStateTextureBindings ;
2012-05-18 09:45:23 +02:00
texBind -> addBinding ( texture . p (), sampler . p (), "u_texture2D" );
eff -> setRenderState ( texBind . p ());
// Hardware independent:
updateCommonEffect ( eff . p ());
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void ScalarMapperEffectGenerator :: updateForFixedFunctionRendering ( cvf :: Effect * effect ) const
{
cvf :: ref < cvf :: Effect > eff = effect ;
2012-10-02 10:17:52 +02:00
cvf :: ref < cvf :: RenderStateMaterial_FF > mat = new cvf :: RenderStateMaterial_FF ( cvf :: Color3 :: WHITE );
2012-05-18 09:45:23 +02:00
eff -> setRenderState ( mat . p ());
2012-10-02 10:17:52 +02:00
cvf :: ref < cvf :: RenderStateLighting_FF > lighting = new cvf :: RenderStateLighting_FF ;
2012-05-18 09:45:23 +02:00
lighting -> enableTwoSided ( true );
2015-06-17 15:00:20 +02:00
lighting -> enable ( ! m_disableLighting );
2012-05-18 09:45:23 +02:00
eff -> setRenderState ( lighting . p ());
// Result mapping texture
2012-08-31 19:12:47 +02:00
m_textureImage = new cvf :: TextureImage ;
m_scalarMapper -> updateTexture ( m_textureImage . p ());
2012-05-18 09:45:23 +02:00
2012-08-31 19:12:47 +02:00
cvf :: ref < cvf :: TextureImage > modTexImg = ScalarMapperEffectGenerator :: addAlphaAndUndefStripes ( m_textureImage . p (), m_undefinedColor , m_opacityLevel );
2012-05-18 09:45:23 +02:00
cvf :: ref < cvf :: Texture2D_FF > texture = new cvf :: Texture2D_FF ( modTexImg . p ());
texture -> setWrapMode ( cvf :: Texture2D_FF :: CLAMP );
texture -> setMinFilter ( cvf :: Texture2D_FF :: NEAREST );
texture -> setMagFilter ( cvf :: Texture2D_FF :: NEAREST );
2012-10-02 10:17:52 +02:00
cvf :: ref < cvf :: RenderStateTextureMapping_FF > texMapping = new cvf :: RenderStateTextureMapping_FF ( texture . p ());
2012-05-18 09:45:23 +02:00
eff -> setRenderState ( texMapping . p ());
// Hardware independent:
updateCommonEffect ( eff . p ());
}
//--------------------------------------------------------------------------------------------------
/// It also modifies the texture, and adds two more pixel lines
/// one with a transparent version of the legend color, and one with color for undefined values
//--------------------------------------------------------------------------------------------------
void ScalarMapperEffectGenerator :: updateCommonEffect ( cvf :: Effect * effect ) const
{
CVF_ASSERT ( effect );
2013-12-17 13:11:46 +01:00
if ( m_polygonOffset != PO_NONE )
2012-05-18 09:45:23 +02:00
{
2014-04-08 08:37:22 +02:00
cvf :: ref < cvf :: RenderStatePolygonOffset > polyOffset = EffectGenerator :: createAndConfigurePolygonOffsetRenderState ( m_polygonOffset );
2012-05-18 09:45:23 +02:00
effect -> setRenderState ( polyOffset . p ());
}
// Simple transparency
if ( m_opacityLevel < 1.0f )
{
2012-10-02 10:17:52 +02:00
cvf :: ref < cvf :: RenderStateBlending > blender = new cvf :: RenderStateBlending ;
2012-05-18 09:45:23 +02:00
blender -> configureTransparencyBlending ();
effect -> setRenderState ( blender . p ());
}
// Backface culling
2013-12-18 13:53:32 +01:00
if ( m_faceCulling != FC_NONE )
2012-05-18 09:45:23 +02:00
{
2012-10-02 10:17:52 +02:00
cvf :: ref < cvf :: RenderStateCullFace > faceCulling = new cvf :: RenderStateCullFace ;
2013-12-18 13:53:32 +01:00
if ( m_faceCulling == FC_BACK )
2013-12-18 08:57:10 +01:00
{
faceCulling -> setMode ( cvf :: RenderStateCullFace :: BACK );
}
2013-12-18 13:53:32 +01:00
else if ( m_faceCulling == FC_FRONT )
2013-12-18 08:57:10 +01:00
{
faceCulling -> setMode ( cvf :: RenderStateCullFace :: FRONT );
}
2013-12-18 13:53:32 +01:00
else if ( m_faceCulling == FC_FRONT_AND_BACK )
2013-12-18 08:57:10 +01:00
{
faceCulling -> setMode ( cvf :: RenderStateCullFace :: FRONT_AND_BACK );
}
2012-05-18 09:45:23 +02:00
effect -> setRenderState ( faceCulling . p ());
}
2013-12-19 08:59:28 +01:00
if ( ! m_enableDepthWrite )
{
cvf :: ref < cvf :: RenderStateDepth > depth = new cvf :: RenderStateDepth ;
depth -> enableDepthWrite ( false );
effect -> setRenderState ( depth . p ());
}
2012-05-18 09:45:23 +02:00
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool ScalarMapperEffectGenerator :: isEqual ( const EffectGenerator * other ) const
{
const ScalarMapperEffectGenerator * otherTextureResultEffect = dynamic_cast < const ScalarMapperEffectGenerator *> ( other );
if ( otherTextureResultEffect )
{
if ( m_scalarMapper . p () == otherTextureResultEffect -> m_scalarMapper
&& m_polygonOffset == otherTextureResultEffect -> m_polygonOffset
&& m_opacityLevel == otherTextureResultEffect -> m_opacityLevel
&& m_undefinedColor == otherTextureResultEffect -> m_undefinedColor
2013-12-19 08:59:28 +01:00
&& m_faceCulling == otherTextureResultEffect -> m_faceCulling
2015-06-17 15:00:20 +02:00
&& m_enableDepthWrite == otherTextureResultEffect -> m_enableDepthWrite
&& m_disableLighting == otherTextureResultEffect -> m_disableLighting )
2012-05-18 09:45:23 +02:00
{
2012-08-31 19:12:47 +02:00
cvf :: ref < cvf :: TextureImage > texImg2 = new cvf :: TextureImage ;
otherTextureResultEffect -> m_scalarMapper -> updateTexture ( texImg2 . p ());
return ScalarMapperEffectGenerator :: isImagesEqual ( m_textureImage . p (), texImg2 . p ());
2012-05-18 09:45:23 +02:00
}
}
return false ;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
EffectGenerator * ScalarMapperEffectGenerator :: copy () const
{
ScalarMapperEffectGenerator * scEffGen = new ScalarMapperEffectGenerator ( m_scalarMapper . p (), m_polygonOffset );
2012-08-31 19:12:47 +02:00
scEffGen -> m_textureImage = m_textureImage ;
2012-05-18 09:45:23 +02:00
scEffGen -> m_opacityLevel = m_opacityLevel ;
scEffGen -> m_undefinedColor = m_undefinedColor ;
2013-12-18 13:53:32 +01:00
scEffGen -> m_faceCulling = m_faceCulling ;
2013-12-19 08:59:28 +01:00
scEffGen -> m_enableDepthWrite = m_enableDepthWrite ;
2015-06-17 15:00:20 +02:00
scEffGen -> m_disableLighting = m_disableLighting ;
2012-05-18 09:45:23 +02:00
return scEffGen ;
}
//--------------------------------------------------------------------------------------------------
/// Modifies the supplied one line texture by adding two more pixel lines
/// one with a transparent version of the legend color, and one with color for undefined values
//--------------------------------------------------------------------------------------------------
cvf :: ref < cvf :: TextureImage >
ScalarMapperEffectGenerator :: addAlphaAndUndefStripes ( const cvf :: TextureImage * texImg , const cvf :: Color3f & undefScalarColor , float opacityLevel )
{
CVF_ASSERT ( texImg != NULL );
CVF_ASSERT ( texImg -> height () == 1 );
cvf :: ref < cvf :: TextureImage > modTexImg = new cvf :: TextureImage ;
2013-09-06 09:44:57 +02:00
modTexImg -> allocate ( texImg -> width (), texImg -> height () + 3 ); // Make the texture a power of two to avoid behind the scenes scaling and the following artefacts
2012-05-18 09:45:23 +02:00
modTexImg -> fill ( cvf :: Color4ub ( cvf :: Color3ub ( undefScalarColor ), 255 )); // Undefined color
2013-01-22 11:34:47 +01:00
for ( cvf :: uint i = 0 ; i < texImg -> width (); ++ i )
2012-05-18 09:45:23 +02:00
{
cvf :: Color4ub legendColor = texImg -> pixel ( i , 0 );
modTexImg -> setPixel ( i , 0 , legendColor );
legendColor . a () = static_cast < cvf :: ubyte > ( opacityLevel * 255 );
modTexImg -> setPixel ( i , 1 , legendColor );
2013-09-06 09:44:57 +02:00
modTexImg -> setPixel ( i , 2 , legendColor );
2012-05-18 09:45:23 +02:00
}
return modTexImg ;
}
2012-08-31 19:12:47 +02:00
//--------------------------------------------------------------------------------------------------
/// Tests whether two texture images are equal. It might in some rare cases not detect the difference
/// but to make the comparison fast only some sampling points are used. If both pointers are NULL,
/// they are considered equal.
//--------------------------------------------------------------------------------------------------
bool ScalarMapperEffectGenerator :: isImagesEqual ( const cvf :: TextureImage * texImg1 , const cvf :: TextureImage * texImg2 )
{
if ( texImg1 == NULL && texImg2 == NULL ) return true ;
if ( texImg1 != NULL && texImg2 != NULL
&& texImg1 -> height () == texImg2 -> height ()
&& texImg1 -> width () == texImg2 -> width ()
&& texImg1 -> width () > 0 && texImg1 -> height () > 0
&& texImg1 -> pixel ( 0 , 0 ) == texImg2 -> pixel ( 0 , 0 )
&& texImg1 -> pixel ( texImg1 -> width () - 1 , texImg1 -> height () - 1 ) == texImg2 -> pixel ( texImg1 -> width () - 1 , texImg1 -> height () - 1 )
&& texImg1 -> pixel ( texImg1 -> width () / 2 , texImg1 -> height () / 2 ) == texImg2 -> pixel ( texImg1 -> width () / 2 , texImg1 -> height () / 2 )
&& texImg1 -> pixel ( texImg1 -> width () / 4 , texImg1 -> height () / 4 ) == texImg2 -> pixel ( texImg1 -> width () / 4 , texImg1 -> height () / 4 )
&& texImg1 -> pixel ( texImg1 -> width () / 2 + texImg1 -> width () / 4 , texImg1 -> height () / 2 + texImg1 -> height () / 4 ) == texImg2 -> pixel ( texImg1 -> width () / 2 + texImg1 -> width () / 4 , texImg1 -> height () / 2 + texImg1 -> height () / 4 )
)
{
return true ;
}
return false ;
}
2012-05-18 09:45:23 +02:00
//==================================================================================================
//
// ScalarMapperMeshEffectGenerator
//
//==================================================================================================
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
ScalarMapperMeshEffectGenerator :: ScalarMapperMeshEffectGenerator ( const cvf :: ScalarMapper * scalarMapper )
: m_undefinedColor ( cvf :: Color3 :: GRAY )
{
m_scalarMapper = scalarMapper ;
m_opacityLevel = 1.0f ;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void ScalarMapperMeshEffectGenerator :: updateForShaderBasedRendering ( cvf :: Effect * effect ) const
{
cvf :: ref < cvf :: Effect > eff = effect ;
cvf :: ShaderProgramGenerator gen ( "ScalarMapperMeshEffectGenerator" , cvf :: ShaderSourceProvider :: instance ());
gen . addVertexCode ( cvf :: ShaderSourceRepository :: vs_Standard );
gen . addFragmentCode ( cvf :: ShaderSourceRepository :: src_Texture );
gen . addFragmentCode ( cvf :: ShaderSourceRepository :: fs_Unlit );
cvf :: ref < cvf :: ShaderProgram > prog = gen . generate ();
eff -> setShaderProgram ( prog . p ());
// Result mapping texture
2012-08-31 19:12:47 +02:00
m_textureImage = new cvf :: TextureImage ;
m_scalarMapper -> updateTexture ( m_textureImage . p ());
2012-05-18 09:45:23 +02:00
2012-08-31 19:12:47 +02:00
cvf :: ref < cvf :: TextureImage > modTexImg = ScalarMapperEffectGenerator :: addAlphaAndUndefStripes ( m_textureImage . p (), m_undefinedColor , m_opacityLevel );
2012-05-18 09:45:23 +02:00
cvf :: ref < cvf :: Texture > texture = new cvf :: Texture ( modTexImg . p ());
cvf :: ref < cvf :: Sampler > sampler = new cvf :: Sampler ;
sampler -> setWrapMode ( cvf :: Sampler :: CLAMP_TO_EDGE );
sampler -> setMinFilter ( cvf :: Sampler :: NEAREST );
sampler -> setMagFilter ( cvf :: Sampler :: NEAREST );
2012-10-02 10:17:52 +02:00
cvf :: ref < cvf :: RenderStateTextureBindings > texBind = new cvf :: RenderStateTextureBindings ;
2012-05-18 09:45:23 +02:00
texBind -> addBinding ( texture . p (), sampler . p (), "u_texture2D" );
eff -> setRenderState ( texBind . p ());
// Hardware independent:
updateCommonEffect ( eff . p ());
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void ScalarMapperMeshEffectGenerator :: updateForFixedFunctionRendering ( cvf :: Effect * effect ) const
{
cvf :: ref < cvf :: Effect > eff = effect ;
2012-10-02 10:17:52 +02:00
eff -> setRenderState ( new cvf :: RenderStateMaterial_FF ( cvf :: Color3 :: WHITE ));
eff -> setRenderState ( new cvf :: RenderStatePolygonMode ( cvf :: RenderStatePolygonMode :: LINE ));
eff -> setRenderState ( new cvf :: RenderStateDepth ( true , cvf :: RenderStateDepth :: LEQUAL ));
eff -> setRenderState ( new cvf :: RenderStateLighting_FF ( false ));
2012-05-18 09:45:23 +02:00
// Result mapping texture
2012-08-31 19:12:47 +02:00
m_textureImage = new cvf :: TextureImage ;
m_scalarMapper -> updateTexture ( m_textureImage . p ());
2012-05-18 09:45:23 +02:00
2012-08-31 19:12:47 +02:00
cvf :: ref < cvf :: TextureImage > modTexImg = ScalarMapperEffectGenerator :: addAlphaAndUndefStripes ( m_textureImage . p (), m_undefinedColor , m_opacityLevel );
2012-05-18 09:45:23 +02:00
cvf :: ref < cvf :: Texture2D_FF > texture = new cvf :: Texture2D_FF ( modTexImg . p ());
texture -> setWrapMode ( cvf :: Texture2D_FF :: CLAMP );
texture -> setMinFilter ( cvf :: Texture2D_FF :: NEAREST );
texture -> setMagFilter ( cvf :: Texture2D_FF :: NEAREST );
2012-10-02 10:17:52 +02:00
cvf :: ref < cvf :: RenderStateTextureMapping_FF > texMapping = new cvf :: RenderStateTextureMapping_FF ( texture . p ());
texMapping -> setTextureFunction ( cvf :: RenderStateTextureMapping_FF :: DECAL );
2012-05-18 09:45:23 +02:00
eff -> setRenderState ( texMapping . p ());
// Hardware independent:
updateCommonEffect ( eff . p ());
}
//--------------------------------------------------------------------------------------------------
/// It also modifies the texture, and adds two more pixel lines
/// one with a transparent version of the legend color, and one with color for undefined values
//--------------------------------------------------------------------------------------------------
void ScalarMapperMeshEffectGenerator :: updateCommonEffect ( cvf :: Effect * effect ) const
{
CVF_ASSERT ( effect );
// Simple transparency
if ( m_opacityLevel < 1.0f )
{
2012-10-02 10:17:52 +02:00
cvf :: ref < cvf :: RenderStateBlending > blender = new cvf :: RenderStateBlending ;
2012-05-18 09:45:23 +02:00
blender -> configureTransparencyBlending ();
effect -> setRenderState ( blender . p ());
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool ScalarMapperMeshEffectGenerator :: isEqual ( const EffectGenerator * other ) const
{
const ScalarMapperMeshEffectGenerator * otherTextureResultEffect = dynamic_cast < const ScalarMapperMeshEffectGenerator *> ( other );
if ( otherTextureResultEffect )
{
if ( m_scalarMapper . p () == otherTextureResultEffect -> m_scalarMapper
&& m_opacityLevel == otherTextureResultEffect -> m_opacityLevel
&& m_undefinedColor == otherTextureResultEffect -> m_undefinedColor )
{
2012-08-31 19:12:47 +02:00
cvf :: ref < cvf :: TextureImage > texImg2 = new cvf :: TextureImage ;
otherTextureResultEffect -> m_scalarMapper -> updateTexture ( texImg2 . p ());
return ScalarMapperEffectGenerator :: isImagesEqual ( m_textureImage . p (), texImg2 . p ());
2012-05-18 09:45:23 +02:00
}
}
return false ;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
EffectGenerator * ScalarMapperMeshEffectGenerator :: copy () const
{
ScalarMapperMeshEffectGenerator * scEffGen = new ScalarMapperMeshEffectGenerator ( m_scalarMapper . p ());
2012-08-31 19:12:47 +02:00
scEffGen -> m_textureImage = m_textureImage ;
2012-05-18 09:45:23 +02:00
scEffGen -> m_opacityLevel = m_opacityLevel ;
scEffGen -> m_undefinedColor = m_undefinedColor ;
return scEffGen ;
}
//==================================================================================================
//
// MeshEffectGenerator
//
//==================================================================================================
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
MeshEffectGenerator :: MeshEffectGenerator ( const cvf :: Color3f & color )
{
m_color = color ;
2015-07-29 14:19:43 +02:00
m_lineStipple = false ;
2012-05-18 09:45:23 +02:00
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void MeshEffectGenerator :: updateForShaderBasedRendering ( cvf :: Effect * effect ) const
{
cvf :: ShaderProgramGenerator spGen ( "Mesh" , cvf :: ShaderSourceProvider :: instance ());
spGen . addVertexCode ( cvf :: ShaderSourceRepository :: vs_Standard );
spGen . addFragmentCode ( cvf :: ShaderSourceRepository :: src_Color );
spGen . addFragmentCode ( cvf :: ShaderSourceRepository :: fs_Unlit );
cvf :: ref < cvf :: ShaderProgram > shaderProg = spGen . generate ();
cvf :: ref < cvf :: Effect > eff = effect ;
eff -> setShaderProgram ( shaderProg . p ());
eff -> setUniform ( new cvf :: UniformFloat ( "u_color" , cvf :: Color4f ( m_color , 1.0 )));
2015-07-29 14:19:43 +02:00
if ( m_lineStipple )
{
2015-08-13 15:43:17 +02:00
// TODO: Use when VizFwk is updated
2015-07-29 14:19:43 +02:00
//eff->setRenderState(new cvf::RenderStateLineStipple_FF);
}
2012-05-18 09:45:23 +02:00
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void MeshEffectGenerator :: updateForFixedFunctionRendering ( cvf :: Effect * effect ) const
{
cvf :: ref < cvf :: Effect > eff = effect ;
2012-10-02 10:17:52 +02:00
eff -> setRenderState ( new cvf :: RenderStateMaterial_FF ( m_color ));
eff -> setRenderState ( new cvf :: RenderStatePolygonMode ( cvf :: RenderStatePolygonMode :: LINE ));
eff -> setRenderState ( new cvf :: RenderStateDepth ( true , cvf :: RenderStateDepth :: LEQUAL ));
eff -> setRenderState ( new cvf :: RenderStateLighting_FF ( false ));
2012-05-18 09:45:23 +02:00
2015-07-29 14:19:43 +02:00
if ( m_lineStipple )
{
2015-08-13 15:43:17 +02:00
// TODO: Use when VizFwk is updated
2015-07-29 14:19:43 +02:00
//eff->setRenderState(new cvf::RenderStateLineStipple_FF);
}
2012-05-18 09:45:23 +02:00
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool MeshEffectGenerator :: isEqual ( const EffectGenerator * other ) const
{
const MeshEffectGenerator * otherMesh = dynamic_cast < const MeshEffectGenerator *> ( other );
if ( otherMesh )
{
2015-07-29 14:19:43 +02:00
if ( m_color != otherMesh -> m_color )
2012-05-18 09:45:23 +02:00
{
2015-07-29 14:19:43 +02:00
return false ;
}
if ( m_lineStipple != otherMesh -> m_lineStipple )
{
return false ;
2012-05-18 09:45:23 +02:00
}
2015-07-29 14:19:43 +02:00
return true ;
2012-05-18 09:45:23 +02:00
}
return false ;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
EffectGenerator * MeshEffectGenerator :: copy () const
{
2015-07-29 14:19:43 +02:00
MeshEffectGenerator * effGen = new MeshEffectGenerator ( m_color );
effGen -> setLineStipple ( m_lineStipple );
return effGen ;
2012-05-18 09:45:23 +02:00
}
2015-11-17 16:26:07 +01:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
TextEffectGenerator :: TextEffectGenerator ()
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool TextEffectGenerator :: isEqual ( const EffectGenerator * other ) const
{
const TextEffectGenerator * otherSurfaceEffect = dynamic_cast < const TextEffectGenerator *> ( other );
if ( otherSurfaceEffect )
{
return true ;
}
return false ;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
EffectGenerator * TextEffectGenerator :: copy () const
{
TextEffectGenerator * effGen = new TextEffectGenerator ;
return effGen ;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void TextEffectGenerator :: updateForShaderBasedRendering ( cvf :: Effect * effect ) const
{
// See OpenGLResourceManager::getLinkedTextShaderProgram for code to be used here
// Detected some issues on RHEL 6 related to text, so use an empty effect for now
// Will fall back to fixed function rendering
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void TextEffectGenerator :: updateForFixedFunctionRendering ( cvf :: Effect * effect ) const
{
}
2012-05-18 09:45:23 +02:00
} // End namespace caf