1 pixel wide lines using OpenGL shaders.
This commit is contained in:
parent
64122ae057
commit
20c86db71f
|
@ -783,22 +783,23 @@ void OPENGL_GAL::DrawCircle( const VECTOR2D& aCenterPoint, double aRadius )
|
||||||
color4( fillColor.r, fillColor.g, fillColor.b, fillColor.a );
|
color4( fillColor.r, fillColor.g, fillColor.b, fillColor.a );
|
||||||
|
|
||||||
/* Draw a triangle that contains the circle, then shade it leaving only the circle.
|
/* Draw a triangle that contains the circle, then shade it leaving only the circle.
|
||||||
Parameters given to setShader are relative coordinates of the triangle's vertices.
|
Parameters given to setShader are indices of the triangle's vertices
|
||||||
|
(if you want to understand more, check the vertex shader source [shader.vert]).
|
||||||
Shader uses this coordinates to determine if fragments are inside the circle or not.
|
Shader uses this coordinates to determine if fragments are inside the circle or not.
|
||||||
v2
|
v2
|
||||||
/\
|
/\
|
||||||
//\\
|
//\\
|
||||||
v0 /_\/_\ v1
|
v0 /_\/_\ v1
|
||||||
*/
|
*/
|
||||||
setShader( SHADER_FILLED_CIRCLE, -sqrt( 3.0f ), -1.0f );
|
setShader( SHADER_FILLED_CIRCLE, 1.0 );
|
||||||
vertex3( aCenterPoint.x - aRadius * sqrt( 3.0f ), // v0
|
vertex3( aCenterPoint.x - aRadius * sqrt( 3.0f ),
|
||||||
aCenterPoint.y - aRadius, layerDepth );
|
aCenterPoint.y - aRadius, layerDepth ); // v0
|
||||||
|
|
||||||
setShader( SHADER_FILLED_CIRCLE, sqrt( 3.0f ), -1.0f );
|
setShader( SHADER_FILLED_CIRCLE, 2.0 );
|
||||||
vertex3( aCenterPoint.x + aRadius * sqrt( 3.0f ), // v1
|
vertex3( aCenterPoint.x + aRadius * sqrt( 3.0f ),
|
||||||
aCenterPoint.y - aRadius, layerDepth );
|
aCenterPoint.y - aRadius, layerDepth ); // v1
|
||||||
|
|
||||||
setShader( SHADER_FILLED_CIRCLE, 0.0f, 2.0f );
|
setShader( SHADER_FILLED_CIRCLE, 3.0 );
|
||||||
vertex3( aCenterPoint.x, aCenterPoint.y + aRadius * 2.0f, layerDepth ); // v2
|
vertex3( aCenterPoint.x, aCenterPoint.y + aRadius * 2.0f, layerDepth ); // v2
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -807,30 +808,25 @@ void OPENGL_GAL::DrawCircle( const VECTOR2D& aCenterPoint, double aRadius )
|
||||||
color4( strokeColor.r, strokeColor.g, strokeColor.b, strokeColor.a );
|
color4( strokeColor.r, strokeColor.g, strokeColor.b, strokeColor.a );
|
||||||
|
|
||||||
/* Draw a triangle that contains the circle, then shade it leaving only the circle.
|
/* Draw a triangle that contains the circle, then shade it leaving only the circle.
|
||||||
Parameters given to setShader are relative coordinates of the triangle's vertices
|
Parameters given to setShader are indices of the triangle's vertices
|
||||||
|
(if you want to understand more, check the vertex shader source [shader.vert]).
|
||||||
and the line width. Shader uses this coordinates to determine if fragments are inside
|
and the line width. Shader uses this coordinates to determine if fragments are inside
|
||||||
the circle or not. Width parameter has to be passed as a ratio of inner radius
|
the circle or not.
|
||||||
to outer radius.
|
|
||||||
v2
|
v2
|
||||||
/\
|
/\
|
||||||
//\\
|
//\\
|
||||||
v0 /_\/_\ v1
|
v0 /_\/_\ v1
|
||||||
*/
|
*/
|
||||||
float outerRadius = aRadius + ( lineWidth / 2.0f );
|
setShader( SHADER_STROKED_CIRCLE, 1.0, aRadius, lineWidth );
|
||||||
float innerRadius = aRadius - ( lineWidth / 2.0f );
|
vertex3( aCenterPoint.x - aRadius * sqrt( 3.0f ),
|
||||||
float relWidth = innerRadius / outerRadius;
|
aCenterPoint.y - aRadius, layerDepth ); // v0
|
||||||
|
|
||||||
setShader( SHADER_STROKED_CIRCLE, -sqrt( 3.0f ), -1.0f, relWidth );
|
setShader( SHADER_STROKED_CIRCLE, 2.0, aRadius, lineWidth );
|
||||||
vertex3( aCenterPoint.x - outerRadius * sqrt( 3.0f ), // v0
|
vertex3( aCenterPoint.x + aRadius * sqrt( 3.0f ),
|
||||||
aCenterPoint.y - outerRadius, layerDepth );
|
aCenterPoint.y - aRadius, layerDepth ); // v1
|
||||||
|
|
||||||
setShader( SHADER_STROKED_CIRCLE, sqrt( 3.0f ), -1.0f, relWidth );
|
setShader( SHADER_STROKED_CIRCLE, 3.0, aRadius, lineWidth );
|
||||||
vertex3( aCenterPoint.x + outerRadius * sqrt( 3.0f ), // v1
|
vertex3( aCenterPoint.x, aCenterPoint.y + aRadius * 2.0f, layerDepth ); // v2
|
||||||
aCenterPoint.y - outerRadius, layerDepth );
|
|
||||||
|
|
||||||
setShader( SHADER_STROKED_CIRCLE, 0.0f, 2.0f, relWidth );
|
|
||||||
vertex3( aCenterPoint.x, // v2
|
|
||||||
aCenterPoint.y + outerRadius * 2.0f, layerDepth );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
@ -931,20 +927,21 @@ void OPENGL_GAL::drawFilledSemiCircle( const VECTOR2D& aCenterPoint, double aRad
|
||||||
Rotate( aAngle );
|
Rotate( aAngle );
|
||||||
|
|
||||||
/* Draw a triangle that contains the semicircle, then shade it to leave only the semicircle.
|
/* Draw a triangle that contains the semicircle, then shade it to leave only the semicircle.
|
||||||
Parameters given to setShader are relative coordinates of the triangle's vertices.
|
Parameters given to setShader are indices of the triangle's vertices
|
||||||
|
(if you want to understand more, check the vertex shader source [shader.vert]).
|
||||||
Shader uses this coordinates to determine if fragments are inside the semicircle or not.
|
Shader uses this coordinates to determine if fragments are inside the semicircle or not.
|
||||||
v2
|
v2
|
||||||
/\
|
/\
|
||||||
/__\
|
/__\
|
||||||
v0 //__\\ v1
|
v0 //__\\ v1
|
||||||
*/
|
*/
|
||||||
setShader( SHADER_FILLED_CIRCLE, -3.0f / sqrt( 3.0f ), 0.0f );
|
setShader( SHADER_FILLED_CIRCLE, 4.0f );
|
||||||
vertex3( -aRadius * 3.0f / sqrt( 3.0f ), 0.0f, layerDepth ); // v0
|
vertex3( -aRadius * 3.0f / sqrt( 3.0f ), 0.0f, layerDepth ); // v0
|
||||||
|
|
||||||
setShader( SHADER_FILLED_CIRCLE, 3.0f / sqrt( 3.0f ), 0.0f );
|
setShader( SHADER_FILLED_CIRCLE, 5.0f );
|
||||||
vertex3( aRadius * 3.0f / sqrt( 3.0f ), 0.0f, layerDepth ); // v1
|
vertex3( aRadius * 3.0f / sqrt( 3.0f ), 0.0f, layerDepth ); // v1
|
||||||
|
|
||||||
setShader( SHADER_FILLED_CIRCLE, 0.0f, 2.0f );
|
setShader( SHADER_FILLED_CIRCLE, 6.0f );
|
||||||
vertex3( 0.0f, aRadius * 2.0f, layerDepth ); // v2
|
vertex3( 0.0f, aRadius * 2.0f, layerDepth ); // v2
|
||||||
|
|
||||||
Restore();
|
Restore();
|
||||||
|
@ -973,26 +970,22 @@ void OPENGL_GAL::drawStrokedSemiCircle( const VECTOR2D& aCenterPoint, double aRa
|
||||||
Rotate( aAngle );
|
Rotate( aAngle );
|
||||||
|
|
||||||
/* Draw a triangle that contains the semicircle, then shade it to leave only the semicircle.
|
/* Draw a triangle that contains the semicircle, then shade it to leave only the semicircle.
|
||||||
Parameters given to setShader are relative coordinates of the triangle's vertices
|
Parameters given to setShader are indices of the triangle's vertices
|
||||||
and the line width. Shader uses this coordinates to determine if fragments are inside
|
(if you want to understand more, check the vertex shader source [shader.vert]), the
|
||||||
the semicircle or not. Width parameter has to be passed as a ratio of inner radius
|
radius and the line width. Shader uses this coordinates to determine if fragments are
|
||||||
to outer radius.
|
inside the semicircle or not.
|
||||||
v2
|
v2
|
||||||
/\
|
/\
|
||||||
/__\
|
/__\
|
||||||
v0 //__\\ v1
|
v0 //__\\ v1
|
||||||
*/
|
*/
|
||||||
float outerRadius = aRadius;
|
setShader( SHADER_STROKED_CIRCLE, 4.0f, aRadius, lineWidth );
|
||||||
float innerRadius = aRadius - lineWidth;
|
|
||||||
float relWidth = innerRadius / outerRadius;
|
|
||||||
|
|
||||||
setShader( SHADER_STROKED_CIRCLE, -3.0f / sqrt( 3.0f ), 0.0f, relWidth );
|
|
||||||
vertex3( -aRadius * 3.0f / sqrt( 3.0f ), 0.0f, layerDepth ); // v0
|
vertex3( -aRadius * 3.0f / sqrt( 3.0f ), 0.0f, layerDepth ); // v0
|
||||||
|
|
||||||
setShader( SHADER_STROKED_CIRCLE, 3.0f / sqrt( 3.0f ), 0.0f, relWidth );
|
setShader( SHADER_STROKED_CIRCLE, 5.0f, aRadius, lineWidth );
|
||||||
vertex3( aRadius * 3.0f / sqrt( 3.0f ), 0.0f, layerDepth ); // v1
|
vertex3( aRadius * 3.0f / sqrt( 3.0f ), 0.0f, layerDepth ); // v1
|
||||||
|
|
||||||
setShader( SHADER_STROKED_CIRCLE, 0.0f, 2.0f, relWidth );
|
setShader( SHADER_STROKED_CIRCLE, 6.0f, aRadius, lineWidth );
|
||||||
vertex3( 0.0f, aRadius * 2.0f, layerDepth ); // v2
|
vertex3( 0.0f, aRadius * 2.0f, layerDepth ); // v2
|
||||||
|
|
||||||
Restore();
|
Restore();
|
||||||
|
|
|
@ -32,20 +32,25 @@ const float SHADER_FILLED_CIRCLE = 2.0;
|
||||||
const float SHADER_STROKED_CIRCLE = 3.0;
|
const float SHADER_STROKED_CIRCLE = 3.0;
|
||||||
|
|
||||||
varying vec4 shaderParams;
|
varying vec4 shaderParams;
|
||||||
|
varying vec2 circleCoords;
|
||||||
|
|
||||||
void filledCircle( vec2 aCoord )
|
void filledCircle( vec2 aCoord )
|
||||||
{
|
{
|
||||||
if( dot( aCoord, aCoord ) < 1.0 )
|
if( dot( aCoord, aCoord ) < 1.0f )
|
||||||
gl_FragColor = gl_Color;
|
gl_FragColor = gl_Color;
|
||||||
else
|
else
|
||||||
discard;
|
discard;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void strokedCircle( vec2 aCoord, float aWidth )
|
void strokedCircle( vec2 aCoord, float aRadius, float aWidth )
|
||||||
{
|
{
|
||||||
|
float outerRadius = aRadius;
|
||||||
|
float innerRadius = aRadius - aWidth;
|
||||||
|
float relWidth = innerRadius / outerRadius;
|
||||||
|
|
||||||
if( ( dot( aCoord, aCoord ) < 1.0 ) &&
|
if( ( dot( aCoord, aCoord ) < 1.0 ) &&
|
||||||
( dot( aCoord, aCoord ) > aWidth * aWidth ) )
|
( dot( aCoord, aCoord ) > relWidth * relWidth ) )
|
||||||
gl_FragColor = gl_Color;
|
gl_FragColor = gl_Color;
|
||||||
else
|
else
|
||||||
discard;
|
discard;
|
||||||
|
@ -56,11 +61,11 @@ void main()
|
||||||
{
|
{
|
||||||
if( shaderParams[0] == SHADER_FILLED_CIRCLE )
|
if( shaderParams[0] == SHADER_FILLED_CIRCLE )
|
||||||
{
|
{
|
||||||
filledCircle( vec2( shaderParams[1], shaderParams[2] ) );
|
filledCircle( circleCoords );
|
||||||
}
|
}
|
||||||
else if( shaderParams[0] == SHADER_STROKED_CIRCLE )
|
else if( shaderParams[0] == SHADER_STROKED_CIRCLE )
|
||||||
{
|
{
|
||||||
strokedCircle( vec2( shaderParams[1], shaderParams[2] ), shaderParams[3] );
|
strokedCircle( circleCoords, shaderParams[2], shaderParams[3] );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -31,8 +31,12 @@ const float SHADER_LINE = 1.0;
|
||||||
const float SHADER_FILLED_CIRCLE = 2.0;
|
const float SHADER_FILLED_CIRCLE = 2.0;
|
||||||
const float SHADER_STROKED_CIRCLE = 3.0;
|
const float SHADER_STROKED_CIRCLE = 3.0;
|
||||||
|
|
||||||
|
// Minimum line width
|
||||||
|
const float MIN_WIDTH = 1.0;
|
||||||
|
|
||||||
attribute vec4 attrShaderParams;
|
attribute vec4 attrShaderParams;
|
||||||
varying vec4 shaderParams;
|
varying vec4 shaderParams;
|
||||||
|
varying vec2 circleCoords;
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
|
@ -45,8 +49,8 @@ void main()
|
||||||
float worldScale = gl_ModelViewMatrix[0][0];
|
float worldScale = gl_ModelViewMatrix[0][0];
|
||||||
float scale;
|
float scale;
|
||||||
|
|
||||||
// Make lines appear to be at least 1 pixel width
|
// Make lines appear to be at least 1 pixel wide
|
||||||
if( worldScale * lineWidth < 1.0 )
|
if( worldScale * lineWidth < MIN_WIDTH )
|
||||||
scale = 1.0 / ( worldScale * lineWidth );
|
scale = 1.0 / ( worldScale * lineWidth );
|
||||||
else
|
else
|
||||||
scale = 1.0;
|
scale = 1.0;
|
||||||
|
@ -54,6 +58,37 @@ void main()
|
||||||
gl_Position = gl_ModelViewProjectionMatrix *
|
gl_Position = gl_ModelViewProjectionMatrix *
|
||||||
( gl_Vertex + vec4( shaderParams.yz * scale, 0.0, 0.0 ) );
|
( gl_Vertex + vec4( shaderParams.yz * scale, 0.0, 0.0 ) );
|
||||||
}
|
}
|
||||||
|
else if( ( shaderParams[0] == SHADER_STROKED_CIRCLE ) ||
|
||||||
|
( shaderParams[0] == SHADER_FILLED_CIRCLE ) )
|
||||||
|
{
|
||||||
|
// Compute relative circle coordinates basing on indices
|
||||||
|
// Circle
|
||||||
|
if( shaderParams[1] == 1.0f )
|
||||||
|
circleCoords = vec2( -sqrt( 3.0f ), -1.0f );
|
||||||
|
else if( shaderParams[1] == 2.0f )
|
||||||
|
circleCoords = vec2( sqrt( 3.0f ), -1.0f );
|
||||||
|
else if( shaderParams[1] == 3.0f )
|
||||||
|
circleCoords = vec2( 0.0f, 2.0f );
|
||||||
|
|
||||||
|
// Semicircle
|
||||||
|
else if( shaderParams[1] == 4.0f )
|
||||||
|
circleCoords = vec2( -3.0f / sqrt( 3.0f ), 0.0f );
|
||||||
|
else if( shaderParams[1] == 5.0f )
|
||||||
|
circleCoords = vec2( 3.0f / sqrt( 3.0f ), 0.0f );
|
||||||
|
else if( shaderParams[1] == 6.0f )
|
||||||
|
circleCoords = vec2( 0.0f, 2.0f );
|
||||||
|
|
||||||
|
// Make the line appear to be at least 1 pixel wide
|
||||||
|
float lineWidth = shaderParams[3];
|
||||||
|
float worldScale = gl_ModelViewMatrix[0][0];
|
||||||
|
float scale;
|
||||||
|
|
||||||
|
// Make lines appear to be at least 1 pixel width
|
||||||
|
if( worldScale * lineWidth < MIN_WIDTH )
|
||||||
|
shaderParams[3] = shaderParams[3] / ( worldScale * lineWidth );
|
||||||
|
|
||||||
|
gl_Position = ftransform();
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Pass through the coordinates like in the fixed pipeline
|
// Pass through the coordinates like in the fixed pipeline
|
||||||
|
|
Loading…
Reference in New Issue