Commit 03de9718 authored by Christopher Tenter's avatar Christopher Tenter

- add points and dot rendermode

- add option to toggle between gl_PointSize or quad extrusion in geometry shader
parent 6977a82a
......@@ -114,7 +114,8 @@ SplatCloudNode::SplatCloudNode( const SplatCloud &_splatCloud, BaseNode *_parent
vboSelectionsOffset_( -1 ),
vboPickColorsOffset_( -1 ),
pointsizeScale_ ( 1.0f ),
backfaceCulling_ ( false )
backfaceCulling_ ( false ),
geometryShaderQuads_( false )
{
// create a new VBO (will be invalid and rebuilt the next time drawn (or picked))
createVBO();
......@@ -324,7 +325,7 @@ void SplatCloudNode::draw( GLState &_state, const DrawModes::DrawMode &_drawMode
void SplatCloudNode::getRenderObjects( IRenderer* _renderer, GLState& _state, const DrawModes::DrawMode& _drawMode, const Material* _mat )
{
static const int RENDERMODE_POINTS = 0;
static const int RENDERMODE_DOTS = 1;
static const int RENDERMODE_SPLATS = 2;
......@@ -335,7 +336,6 @@ void SplatCloudNode::getRenderObjects( IRenderer* _renderer, GLState& _state, co
else if (_drawMode.containsAtomicDrawMode(dotsDrawMode_))
rendermode = RENDERMODE_DOTS;
else if (_drawMode.containsAtomicDrawMode(pointsDrawMode_)) {
static const int RENDERMODE_POINTS = 0;
rendermode = RENDERMODE_POINTS;
}
else
......@@ -348,6 +348,9 @@ void SplatCloudNode::getRenderObjects( IRenderer* _renderer, GLState& _state, co
obj.depthTest = true;
// backface culling is done manually in shader
obj.culling = false;
// if VBO is invalid or was (partially) modified, then rebuild
if ((vboData_ == 0) || vboModified())
rebuildVBO(_state);
......@@ -419,21 +422,63 @@ void SplatCloudNode::getRenderObjects( IRenderer* _renderer, GLState& _state, co
// render:
// -------
// enable "pointsize by program" depending on current rendermode
if (rendermode == RENDERMODE_SPLATS || rendermode == RENDERMODE_DOTS)
// setup shader
obj.shaderDesc.shadeMode = SG_SHADE_UNLIT;
obj.programPointSize = false;
// test gl_PointSize performance
if (rendermode == RENDERMODE_DOTS)
{
ACG::Vec2f screenSize(_state.viewport_width(), _state.viewport_height());
// obj.setupPointRendering(defaultPointsize_, screenSize);
}
// setup shader
obj.shaderDesc.shadeMode = SG_SHADE_UNLIT;
// obj.shaderDesc.vertexTemplateFile = "SplatCloud_Splats/Vertex_shadergen.glsl";
// obj.shaderDesc.fragmentTemplateFile = "SplatCloud_Splats/Fragment_shadergen.glsl";
obj.shaderDesc.vertexTemplateFile = "SplatCloud_ShaderGen/splat_vs.glsl";
obj.shaderDesc.geometryTemplateFile = "SplatCloud_ShaderGen/splat_gs.glsl";
obj.shaderDesc.fragmentTemplateFile = "SplatCloud_ShaderGen/splat_fs.glsl";
switch (rendermode)
{
case RENDERMODE_SPLATS:
{
if (geometryShaderQuads_)
{
obj.shaderDesc.vertexTemplateFile = "SplatCloud_ShaderGen/splats_quad_vs.glsl";
obj.shaderDesc.geometryTemplateFile = "SplatCloud_ShaderGen/splats_quad_gs.glsl";
obj.shaderDesc.fragmentTemplateFile = "SplatCloud_ShaderGen/splats_quad_fs.glsl";
obj.programPointSize = false;
}
else
{
obj.shaderDesc.vertexTemplateFile = "SplatCloud_ShaderGen/splats_psize_vs.glsl";
obj.shaderDesc.fragmentTemplateFile = "SplatCloud_ShaderGen/splats_psize_fs.glsl";
obj.programPointSize = true;
}
} break;
case RENDERMODE_DOTS:
{
if (geometryShaderQuads_)
{
obj.shaderDesc.vertexTemplateFile = "SplatCloud_ShaderGen/dots_quad_vs.glsl";
obj.shaderDesc.geometryTemplateFile = "SplatCloud_ShaderGen/splats_quad_gs.glsl";
obj.shaderDesc.fragmentTemplateFile = "SplatCloud_ShaderGen/splats_quad_fs.glsl";
obj.programPointSize = false;
}
else
{
obj.shaderDesc.vertexTemplateFile = "SplatCloud_ShaderGen/dots_psize_vs.glsl";
obj.programPointSize = true;
}
} break;
case RENDERMODE_POINTS:
{
obj.shaderDesc.vertexTemplateFile = "SplatCloud_ShaderGen/points_vs.glsl";
obj.programPointSize = false;
} break;
default: break;
}
// setup uniforms
/*
......@@ -513,8 +558,6 @@ void SplatCloudNode::getRenderObjects( IRenderer* _renderer, GLState& _state, co
obj.setUniform("defaultPointsize", defaultPointsize_);
obj.setUniform("defaultNormal", defaultNormal_);
obj.programPointSize = true;
if (vboColorsOffset_ != -1)
obj.shaderDesc.vertexColors = true;
......@@ -658,7 +701,7 @@ void SplatCloudNode::rebuildVBO( GLState &_state )
if( _state.color_picking() )
{
// store picking base index
pickingBaseIndex_ = _state.pick_current_index();
pickingBaseIndex_ = static_cast<unsigned int>(_state.pick_current_index());
}
// rebuild data blocks if needed
......
......@@ -183,6 +183,7 @@ public:
inline void setPointsizeScale(float _scale) { pointsizeScale_ = _scale; }
inline void setBackfaceCulling(bool _enable) { backfaceCulling_ = _enable; }
inline void setGeometryShaderQuads(bool _enable) { geometryShaderQuads_ = _enable; }
//----------------------------------------------------------------
......@@ -282,6 +283,7 @@ private:
float pointsizeScale_;
bool backfaceCulling_;
bool geometryShaderQuads_;
};
......
......@@ -340,6 +340,18 @@ void SplatCloudObject::enableBackfaceCulling( bool _enable )
}
//----------------------------------------------------------------
/**
* Enable or disable quad extrusion in geometry shader.
* This only affects the shader pipeline renderers.
*/
void SplatCloudObject::enableGeometryShaderQuads(bool _enable)
{
splatCloudNode_->setGeometryShaderQuads(_enable);
}
//----------------------------------------------------------------
......
......@@ -115,6 +115,10 @@ public:
*/
void enableBackfaceCulling( bool _enable );
/** \brief Enable or disable quad extrusion in geometry shader (shader pipeline)
*/
void enableGeometryShaderQuads( bool _enable );
/** \brief Set the scaling factor for pointsizes for all Shaders
*/
void setPointsizeScale( float _scale );
......
#version 130
// splat shader version compatible with the ACG shader generator
// request common attributes
#define SG_REQUEST_POSVS
#define SG_REQUEST_NORMALVS
uniform float pointsizeScale = 1.0;
uniform bool backfaceCulling = false;
uniform float modelviewScale;
uniform float viewportScaleFov_y;
uniform float defaultPointsize;
uniform vec3 defaultNormal;
void main()
{
#ifdef SG_INPUT_TEXCOORD
(SG_INPUT_TEXCOORD.x is the pointsize in model - coordinates)
float splatPointSize = SG_INPUT_TEXCOORD.x;
#else
float splatPointSize = defaultPointsize;
#endif
// transformation of splat center is done in generated shader code:
SG_VERTEX_BEGIN;
SG_VERTEX_END;
// calculate pointsize
float ecPointsize = modelviewScale * pointsizeScale * splatPointSize;
gl_PointSize = max(viewportScaleFov_y * ecPointsize / gl_Position.w, 1.0);
// use generated SG_OUTPUT variables to do backface culling
if (backfaceCulling && dot(SG_OUTPUT_POSVS, SG_OUTPUT_NORMALVS) > 0.0)
{
// discard vertex
gl_Position.w = 0.0;
}
}
#version 150
// splat shader version compatible with the ACG shader generator
// request common attributes
#define SG_REQUEST_POSVS
#define SG_REQUEST_NORMALOS
#define SG_REQUEST_NORMALVS
out vec3 v2g_tangentVS; // tangent in view space
out vec3 v2g_bitangentVS; // bitangent in view space
out float v2g_pointSize; // point size in view space
uniform float pointsizeScale = 1.0;
uniform bool backfaceCulling = false;
uniform float modelviewScale;
uniform float viewportScaleFov_y;
uniform float defaultPointsize;
uniform vec3 defaultNormal;
void main()
{
#ifdef SG_INPUT_TEXCOORD
(SG_INPUT_TEXCOORD.x is the pointsize in model - coordinates)
float splatPointSize = SG_INPUT_TEXCOORD.x;
#else
float splatPointSize = defaultPointsize;
#endif
// transformation of splat center is done in generated shader code:
SG_VERTEX_BEGIN;
SG_VERTEX_END;
// use generated SG_OUTPUT variables to do backface culling
if (backfaceCulling && dot(SG_OUTPUT_POSVS, SG_OUTPUT_NORMALVS) > 0.0)
{
// discard vertex
gl_Position.w = 0.0;
}
else
{
// screen aligned tangent vectors
v2g_tangentVS = vec3(1, 0, 0);
v2g_bitangentVS = vec3(0, 1, 0);
// calculate pointsize (0.5 factor: scale to point radius instead of diameter)
v2g_pointSize = modelviewScale * pointsizeScale * splatPointSize * 0.5;
}
}
#version 130
// splat shader version compatible with the ACG shader generator
// request common attributes
#define SG_REQUEST_POSVS
#define SG_REQUEST_NORMALOS
#define SG_REQUEST_NORMALVS
uniform float pointsizeScale = 1.0;
uniform bool backfaceCulling = false;
uniform float modelviewScale;
uniform float viewportScaleFov_y;
uniform float defaultPointsize;
uniform vec3 defaultNormal;
void main()
{
// transformation of splat center is done in generated shader code:
SG_VERTEX_BEGIN;
SG_VERTEX_END;
// use generated SG_OUTPUT variables to do backface culling
if (backfaceCulling && dot(SG_OUTPUT_POSVS, SG_OUTPUT_NORMALVS) > 0.0)
{
// discard vertex
gl_Position.w = 0.0;
}
}
#version 130
// splat shader version compatible with the ACG shader generator
in vec3 scaledNormalVS;
in float squaredRadiusVS;
uniform vec4 invViewportScale;
uniform vec4 invViewportTransp;
uniform float viewportScale_z;
uniform float viewportTransp_z;
uniform mat4 invProjection;
void main()
{
SG_FRAGMENT_BEGIN;
SG_FRAGMENT_END;
// calculate fragment's position in eye-coordinates
// - scaled by w-component (not divided) because the fragment's projection (see below) is invariant to this
vec4 ndcPosition = invViewportScale * gl_FragCoord + invViewportTransp;
vec3 scaledPosVS = vec3(invProjection * ndcPosition);
// calculate projection in eye-coordinates of fragment's position along viewing direction onto plane described by splat's center and normal
// - equivalent to: projectionVS = (dot(centerVS,normalVS) / dot(fragmentVS,normalVS)) * fragmentVS
vec3 projectionVS = scaledPosVS / dot(scaledPosVS, scaledNormalVS);
// discard fragment if projection is too far away from splat's center
vec3 centerToProjVS = projectionVS - SG_INPUT_POSVS.xyz;
if (dot(centerToProjVS, centerToProjVS) > squaredRadiusVS)
discard;
// calculate depth of projection in normalized-device-coordinates
vec4 projectionCS = g_mP * vec4(projectionVS, 1.0);
float ndcProjection_z = projectionCS.z / projectionCS.w;
// output depth of projection in window-coordinates
gl_FragDepth = viewportScale_z * ndcProjection_z + viewportTransp_z;
}
#version 130
// splat shader version compatible with the ACG shader generator
// request common attributes
#define SG_REQUEST_POSVS
#define SG_REQUEST_NORMALOS
#define SG_REQUEST_NORMALVS
out vec3 scaledNormalVS;
out float squaredRadiusVS;
uniform float pointsizeScale = 1.0;
uniform bool backfaceCulling = false;
uniform float modelviewScale;
uniform float viewportScaleFov_y;
uniform float defaultPointsize;
uniform vec3 defaultNormal;
void main()
{
#ifdef SG_INPUT_TEXCOORD
(SG_INPUT_TEXCOORD.x is the pointsize in model - coordinates)
float splatPointSize = SG_INPUT_TEXCOORD.x;
#else
float splatPointSize = defaultPointsize;
#endif
// transformation of splat center is done in generated shader code:
SG_VERTEX_BEGIN;
SG_VERTEX_END;
// pass normal in eye-coordinates to fragment-shader
// - scale so we do not have to do this in fragment-shader for every fragment
scaledNormalVS = SG_OUTPUT_NORMALVS / dot(SG_OUTPUT_POSVS.xyz, SG_OUTPUT_NORMALVS);
// calculate pointsize in view space
float pointsizeVS = modelviewScale * pointsizeScale * splatPointSize;
// pass squared radius (= (1/2 pointsize)^2) in eye-coordinates to fragment-shader
squaredRadiusVS = 0.25 * (pointsizeVS * pointsizeVS);
// output pointsize in window-coordinates
// - divided by gl_Position.w to shrink size by distance
// - divided by -normalize(posVS).z because splat could be oriented towards the eye (not necessarily parallel to near-plane)
// - multiply by viewportScaleFov_y to get window coordinates
gl_PointSize = max(pointsizeVS * viewportScaleFov_y / (-normalize(SG_OUTPUT_POSVS.xyz).z * gl_Position.w), 1.0);
// use generated SG_OUTPUT variables to do backface culling
if (backfaceCulling && dot(SG_OUTPUT_POSVS, SG_OUTPUT_NORMALVS) > 0.0)
{
// discard vertex
gl_Position.w = 0.0;
}
}
......@@ -7,7 +7,7 @@ in vec2 g2f_posQS;
void main()
{
// discard fragments outside of splat radius
if( dot( g2f_posQS, g2f_posQS ) > 1 )
if (dot(g2f_posQS, g2f_posQS) > 1)
discard;
SG_FRAGMENT_BEGIN;
......
......@@ -17,10 +17,10 @@ void main()
{
// center of point
vec4 centerVS = SG_INPUT_POSVS[0];
// point size
float pointSize = v2g_pointSize[0].x;
// create normal-aligned quad
vec3 offsetX = v2g_tangentVS[0] * pointSize;
vec3 offsetY = v2g_bitangentVS[0] * pointSize;
......@@ -29,39 +29,39 @@ void main()
vec2 posQS[4] =
{
vec2(-1, 1),
vec2(-1, -1),
vec2(1, 1),
vec2(1, -1)
vec2(-1, -1),
vec2(1, 1),
vec2(1, -1)
};
for (int i = 0; i < 4; ++i)
{
// pass default io from shader generator
sg_MapIO(i);
vec2 uv = posQS[i];
// expand to quad
vec4 posVS = centerVS;
posVS.xyz += uv.x * offsetX + uv.y * offsetY;
// transform
vec4 posCS = g_mP * posVS;
// output
gl_Position = posCS;
g2f_posQS = uv;
#ifdef SG_OUTPUT_POSVS
SG_OUTPUT_POSVS = posVS;
#endif
#ifdef SG_OUTPUT_POSCS
SG_OUTPUT_POSCS = posCS;
#endif
EmitVertex();
vec2 uv = posQS[i];
// expand to quad
vec4 posVS = centerVS;
posVS.xyz += uv.x * offsetX + uv.y * offsetY;
// transform
vec4 posCS = g_mP * posVS;
// output
gl_Position = posCS;
g2f_posQS = uv;
#ifdef SG_OUTPUT_POSVS
SG_OUTPUT_POSVS = posVS;
#endif
#ifdef SG_OUTPUT_POSCS
SG_OUTPUT_POSCS = posCS;
#endif
EmitVertex();
}
EndPrimitive();
}
#version 150
////////////////////////////////////////////////////////////////////////////////////////////
/**/ /**/
/**/ // WARNING: When modifying this file, modify file "PickVertex.glsl" accordingly! /**/
/**/ /**/
////////////////////////////////////////////////////////////////////////////////////////////
// splat shader version compatible with the ACG shader generator
// request common attributes
......@@ -19,7 +12,7 @@ out vec3 v2g_tangentVS; // tangent in view space
out vec3 v2g_bitangentVS; // bitangent in view space
out float v2g_pointSize; // point size in view space
uniform float pointsizeScale = 1.0;
uniform float pointsizeScale = 1.0;
uniform bool backfaceCulling = false;
uniform float modelviewScale;
uniform float viewportScaleFov_y;
......@@ -28,44 +21,38 @@ uniform vec3 defaultNormal;
void main()
{
#ifdef SG_INPUT_NORMALOS
vec3 splatNormal = SG_INPUT_NORMALOS;
#else
vec3 splatNormal = defaultNormal;
#endif
#ifdef SG_INPUT_TEXCOORD
(SG_INPUT_TEXCOORD.x is the pointsize in model-coordinates)
(SG_INPUT_TEXCOORD.x is the pointsize in model - coordinates)
float splatPointSize = SG_INPUT_TEXCOORD.x;
#else
float splatPointSize = defaultPointsize;
float splatPointSize = defaultPointsize;
#endif
// cull if normal is pointing away from eye
if( backfaceCulling && dot( SG_INPUT_POSOS.xyz - g_vCamPos, splatNormal ) > 0.0 ) // second part is evaluated only if backfaceCulling is true
{
// discard vertex
gl_Position.w = 0.0;
}
// transformation of splat center is done in generated shader code:
SG_VERTEX_BEGIN;
SG_VERTEX_END;
// compute normal-aligned tangent vectors
if (all(lessThan(abs(sg_vNormalVS.xy), vec2(0.1, 0.1))))
v2g_tangentVS = cross(sg_vNormalVS, vec3(0, 1, 0));
else
{
SG_VERTEX_BEGIN;
// compute tangent vectors
if (all(lessThan(abs(sg_vNormalVS.xy), vec2(0.1, 0.1))))
v2g_tangentVS = cross(sg_vNormalVS, vec3(0,1,0));
else
v2g_tangentVS = cross(sg_vNormalVS, vec3(0,0,1));
v2g_tangentVS = normalize(v2g_tangentVS);
v2g_bitangentVS = cross(sg_vNormalVS, v2g_tangentVS);
// calculate pointsize
v2g_pointSize = modelviewScale * pointsizeScale * splatPointSize;
SG_VERTEX_END;
}
v2g_tangentVS = cross(sg_vNormalVS, vec3(0, 0, 1));
v2g_tangentVS = normalize(v2g_tangentVS);
v2g_bitangentVS = cross(sg_vNormalVS, v2g_tangentVS);
// calculate pointsize (0.5 factor: scale to point radius instead of diameter)
v2g_pointSize = modelviewScale * pointsizeScale * splatPointSize * 0.5;
// use generated SG_OUTPUT variables to do backface culling
if (backfaceCulling && dot(SG_OUTPUT_POSVS, SG_OUTPUT_NORMALVS) > 0.0)
{
// discard vertex
gl_Position.w = 0.0;
SG_OUTPUT_POSVS.w = 0.0;
}
}
#version 140
// splat shader version compatible with the ACG shader generator
in vec3 ecScaledNormal;
in float ecSquaredRadius;
uniform mat4 invProjection;
uniform vec4 invViewportScale;
uniform vec4 invViewportTransp;
uniform float viewportScale_z;
uniform float viewportTransp_z;
void main()
{
SG_FRAGMENT_BEGIN;
// calculate fragment's position in eye-coordinates
// - scaled by w-component (not divided) because the fragment's projection (see below) is invariant to this
vec4 ndcPosition = invViewportScale * gl_FragCoord + invViewportTransp;
vec3 ecScaledPosition = vec3( invProjection * ndcPosition );