gal/opengl: handle single-pixel line width clamping in hardware (new shader). Correct grid rendering in GAL for pixel-sized lines
This commit is contained in:
parent
b64c6dbf35
commit
711b278248
|
@ -60,13 +60,18 @@ const char kicad_vertex_shader[] = R"SHADER_SOURCE(
|
||||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#version 120
|
#version 130
|
||||||
|
|
||||||
// Shader types
|
// Shader types
|
||||||
const float SHADER_LINE = 1.0;
|
const int SHADER_FILLED_CIRCLE = 2;
|
||||||
const float SHADER_FILLED_CIRCLE = 2.0;
|
const int SHADER_STROKED_CIRCLE = 3;
|
||||||
const float SHADER_STROKED_CIRCLE = 3.0;
|
const int SHADER_FONT = 4;
|
||||||
const float SHADER_FONT = 4.0;
|
const int SHADER_LINE_A = 5;
|
||||||
|
const int SHADER_LINE_B = 6;
|
||||||
|
const int SHADER_LINE_C = 7;
|
||||||
|
const int SHADER_LINE_D = 8;
|
||||||
|
const int SHADER_LINE_E = 9;
|
||||||
|
const int SHADER_LINE_F = 10;
|
||||||
|
|
||||||
// Minimum line width
|
// Minimum line width
|
||||||
const float MIN_WIDTH = 1.0;
|
const float MIN_WIDTH = 1.0;
|
||||||
|
@ -74,58 +79,84 @@ const float MIN_WIDTH = 1.0;
|
||||||
attribute vec4 attrShaderParams;
|
attribute vec4 attrShaderParams;
|
||||||
varying vec4 shaderParams;
|
varying vec4 shaderParams;
|
||||||
varying vec2 circleCoords;
|
varying vec2 circleCoords;
|
||||||
|
uniform float worldPixelSize;
|
||||||
|
|
||||||
void main()
|
void computeLineCoords( bool posture, vec2 offset, vec2 texcoord, vec2 dir )
|
||||||
{
|
{
|
||||||
// Pass attributes to the fragment shader
|
float w = length(offset);
|
||||||
shaderParams = attrShaderParams;
|
|
||||||
|
|
||||||
if( shaderParams[0] == SHADER_LINE )
|
if( w > worldPixelSize )
|
||||||
{
|
{
|
||||||
float lineWidth = shaderParams[3];
|
gl_Position = gl_ModelViewProjectionMatrix * vec4( gl_Vertex.x + offset.x, gl_Vertex.y + offset.y, gl_Vertex.z, gl_Vertex.w );
|
||||||
float worldScale = abs( gl_ModelViewMatrix[0][0] );
|
shaderParams[0] = SHADER_LINE_A;
|
||||||
|
gl_TexCoord[0].st = texcoord;
|
||||||
// Make lines appear to be at least 1 pixel wide
|
|
||||||
if( worldScale * lineWidth < MIN_WIDTH )
|
|
||||||
gl_Position = gl_ModelViewProjectionMatrix *
|
|
||||||
( gl_Vertex + vec4( shaderParams.yz * MIN_WIDTH / ( worldScale * lineWidth ), 0.0, 0.0 ) );
|
|
||||||
else
|
|
||||||
gl_Position = gl_ModelViewProjectionMatrix *
|
|
||||||
( gl_Vertex + vec4( shaderParams.yz, 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.0 )
|
|
||||||
circleCoords = vec2( -sqrt( 3.0 ), -1.0 );
|
|
||||||
else if( shaderParams[1] == 2.0 )
|
|
||||||
circleCoords = vec2( sqrt( 3.0 ), -1.0 );
|
|
||||||
else if( shaderParams[1] == 3.0 )
|
|
||||||
circleCoords = vec2( 0.0, 2.0 );
|
|
||||||
|
|
||||||
// Semicircle
|
|
||||||
else if( shaderParams[1] == 4.0 )
|
|
||||||
circleCoords = vec2( -3.0 / sqrt( 3.0 ), 0.0 );
|
|
||||||
else if( shaderParams[1] == 5.0 )
|
|
||||||
circleCoords = vec2( 3.0 / sqrt( 3.0 ), 0.0 );
|
|
||||||
else if( shaderParams[1] == 6.0 )
|
|
||||||
circleCoords = vec2( 0.0, 2.0 );
|
|
||||||
|
|
||||||
// Make the line appear to be at least 1 pixel wide
|
|
||||||
float lineWidth = shaderParams[3];
|
|
||||||
float worldScale = abs( gl_ModelViewMatrix[0][0] );
|
|
||||||
|
|
||||||
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
|
vec4 pos = gl_Vertex;
|
||||||
gl_Position = ftransform();
|
pos.xy += (posture ? dir : dir.yx ) * worldPixelSize / 2.0;
|
||||||
|
gl_Position = gl_ModelViewProjectionMatrix * pos;
|
||||||
|
shaderParams[0] = SHADER_LINE_B;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
int mode = int( attrShaderParams[0] );
|
||||||
|
|
||||||
|
// Pass attributes to the fragment shader
|
||||||
|
shaderParams = attrShaderParams;
|
||||||
|
|
||||||
|
float aspect = shaderParams.y;
|
||||||
|
vec2 vs = shaderParams.zw;
|
||||||
|
vec2 vp = vec2(-vs.y, vs.x);
|
||||||
|
bool posture = abs( vs.x ) < abs(vs.y);
|
||||||
|
|
||||||
|
switch( mode )
|
||||||
|
{
|
||||||
|
case SHADER_LINE_A: computeLineCoords( posture, vp - vs, vec2( -aspect, -1 ), vec2(-1,0) ); break;
|
||||||
|
case SHADER_LINE_B: computeLineCoords( posture, -vp - vs, vec2( -aspect, 1 ), vec2(1,0) ); break;
|
||||||
|
case SHADER_LINE_C: computeLineCoords( posture, -vp + vs, vec2( aspect, 1 ), vec2(1,0) ); break;
|
||||||
|
case SHADER_LINE_D: computeLineCoords( posture, -vp + vs, vec2( -aspect, -1), vec2(1,0) ); break;
|
||||||
|
case SHADER_LINE_E: computeLineCoords( posture, vp + vs, vec2( -aspect, 1 ), vec2(-1,0) ); break;
|
||||||
|
case SHADER_LINE_F: computeLineCoords( posture, vp - vs, vec2( aspect, 1 ), vec2(-1,0) ); break;
|
||||||
|
case SHADER_STROKED_CIRCLE:
|
||||||
|
case SHADER_FILLED_CIRCLE:
|
||||||
|
{
|
||||||
|
// Compute relative circle coordinates basing on indices
|
||||||
|
// Circle
|
||||||
|
if( shaderParams[1] == 1.0 )
|
||||||
|
circleCoords = vec2( -sqrt( 3.0 ), -1.0 );
|
||||||
|
else if( shaderParams[1] == 2.0 )
|
||||||
|
circleCoords = vec2( sqrt( 3.0 ), -1.0 );
|
||||||
|
else if( shaderParams[1] == 3.0 )
|
||||||
|
circleCoords = vec2( 0.0, 2.0 );
|
||||||
|
|
||||||
|
// Semicircle
|
||||||
|
else if( shaderParams[1] == 4.0 )
|
||||||
|
circleCoords = vec2( -3.0 / sqrt( 3.0 ), 0.0 );
|
||||||
|
else if( shaderParams[1] == 5.0 )
|
||||||
|
circleCoords = vec2( 3.0 / sqrt( 3.0 ), 0.0 );
|
||||||
|
else if( shaderParams[1] == 6.0 )
|
||||||
|
circleCoords = vec2( 0.0, 2.0 );
|
||||||
|
|
||||||
|
// Make the line appear to be at least 1 pixel wide
|
||||||
|
float lineWidth = shaderParams[3];
|
||||||
|
float worldScale = abs( gl_ModelViewMatrix[0][0] );
|
||||||
|
|
||||||
|
if( worldScale * lineWidth < MIN_WIDTH )
|
||||||
|
shaderParams[3] = shaderParams[3] / ( worldScale * lineWidth );
|
||||||
|
|
||||||
|
gl_Position = ftransform();
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
gl_Position = ftransform();
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
gl_FrontColor = gl_Color;
|
gl_FrontColor = gl_Color;
|
||||||
|
@ -162,20 +193,22 @@ const char kicad_fragment_shader[] = R"SHADER_SOURCE(
|
||||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#version 120
|
#version 130
|
||||||
|
|
||||||
// Multi-channel signed distance field
|
// Multi-channel signed distance field
|
||||||
#define USE_MSDF
|
#define USE_MSDF
|
||||||
|
|
||||||
// Shader types
|
// Shader types
|
||||||
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;
|
||||||
const float SHADER_FONT = 4.0;
|
const float SHADER_FONT = 4.0;
|
||||||
|
const float SHADER_LINE_A = 5.0;
|
||||||
|
const float SHADER_LINE_B = 6.0;
|
||||||
|
|
||||||
varying vec4 shaderParams;
|
varying vec4 shaderParams;
|
||||||
varying vec2 circleCoords;
|
varying vec2 circleCoords;
|
||||||
uniform sampler2D fontTexture;
|
uniform sampler2D fontTexture;
|
||||||
|
uniform float worldPixelSize;
|
||||||
|
|
||||||
// Needed to reconstruct the mipmap level / texel derivative
|
// Needed to reconstruct the mipmap level / texel derivative
|
||||||
uniform int fontTextureWidth;
|
uniform int fontTextureWidth;
|
||||||
|
@ -188,6 +221,36 @@ void filledCircle( vec2 aCoord )
|
||||||
discard;
|
discard;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float pixelSegDistance( vec2 aCoord )
|
||||||
|
{
|
||||||
|
if (shaderParams[0] == SHADER_LINE_B)
|
||||||
|
{
|
||||||
|
gl_FragColor = gl_Color;
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
float aspect = shaderParams[1];
|
||||||
|
float dist;
|
||||||
|
vec2 v = vec2( 1.0 - (aspect - abs(aCoord.s)), aCoord.t);
|
||||||
|
|
||||||
|
if( v.x <= 0.0 )
|
||||||
|
{
|
||||||
|
dist = abs(aCoord.t);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dist = length(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
return dist;
|
||||||
|
}
|
||||||
|
|
||||||
|
int isPixelInSegment( vec2 aCoord )
|
||||||
|
{
|
||||||
|
return pixelSegDistance(aCoord) <= 1.0 ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void strokedCircle( vec2 aCoord, float aRadius, float aWidth )
|
void strokedCircle( vec2 aCoord, float aRadius, float aWidth )
|
||||||
{
|
{
|
||||||
|
@ -202,6 +265,15 @@ void strokedCircle( vec2 aCoord, float aRadius, float aWidth )
|
||||||
discard;
|
discard;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void drawLine( vec2 aCoord )
|
||||||
|
{
|
||||||
|
if( isPixelInSegment( aCoord ) != 0)
|
||||||
|
gl_FragColor = gl_Color;
|
||||||
|
else
|
||||||
|
discard;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef USE_MSDF
|
#ifdef USE_MSDF
|
||||||
float median( vec3 v )
|
float median( vec3 v )
|
||||||
{
|
{
|
||||||
|
@ -211,7 +283,11 @@ float median( vec3 v )
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
if( shaderParams[0] == SHADER_FILLED_CIRCLE )
|
if( shaderParams[0] == SHADER_LINE_A )
|
||||||
|
{
|
||||||
|
drawLine( gl_TexCoord[0].st );
|
||||||
|
}
|
||||||
|
else if( shaderParams[0] == SHADER_FILLED_CIRCLE )
|
||||||
{
|
{
|
||||||
filledCircle( circleCoords );
|
filledCircle( circleCoords );
|
||||||
}
|
}
|
||||||
|
|
|
@ -287,6 +287,8 @@ void GPU_NONCACHED_MANAGER::EndDrawing()
|
||||||
m_shader->Deactivate();
|
m_shader->Deactivate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_container->Clear();
|
||||||
|
|
||||||
#ifdef __WXDEBUG__
|
#ifdef __WXDEBUG__
|
||||||
totalRealTime.Stop();
|
totalRealTime.Stop();
|
||||||
wxLogTrace( "GAL_PROFILE",
|
wxLogTrace( "GAL_PROFILE",
|
||||||
|
|
|
@ -319,6 +319,11 @@ bool OPENGL_GAL::updatedGalDisplayOptions( const GAL_DISPLAY_OPTIONS& aOptions )
|
||||||
return refresh;
|
return refresh;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double OPENGL_GAL::getWorldPixelSize() const
|
||||||
|
{
|
||||||
|
auto matrix = GetScreenWorldMatrix();
|
||||||
|
return std::min(std::abs(matrix.GetScale().x), std::abs(matrix.GetScale().y ) );
|
||||||
|
}
|
||||||
|
|
||||||
void OPENGL_GAL::BeginDrawing()
|
void OPENGL_GAL::BeginDrawing()
|
||||||
{
|
{
|
||||||
|
@ -433,6 +438,8 @@ void OPENGL_GAL::BeginDrawing()
|
||||||
// Set shader parameter
|
// Set shader parameter
|
||||||
GLint ufm_fontTexture = shader->AddParameter( "fontTexture" );
|
GLint ufm_fontTexture = shader->AddParameter( "fontTexture" );
|
||||||
GLint ufm_fontTextureWidth = shader->AddParameter( "fontTextureWidth" );
|
GLint ufm_fontTextureWidth = shader->AddParameter( "fontTextureWidth" );
|
||||||
|
ufm_worldPixelSize = shader->AddParameter( "worldPixelSize" );
|
||||||
|
|
||||||
shader->Use();
|
shader->Use();
|
||||||
shader->SetParameter( ufm_fontTexture, (int) FONT_TEXTURE_UNIT );
|
shader->SetParameter( ufm_fontTexture, (int) FONT_TEXTURE_UNIT );
|
||||||
shader->SetParameter( ufm_fontTextureWidth, (int) font_image.width );
|
shader->SetParameter( ufm_fontTextureWidth, (int) font_image.width );
|
||||||
|
@ -442,6 +449,10 @@ void OPENGL_GAL::BeginDrawing()
|
||||||
isBitmapFontInitialized = true;
|
isBitmapFontInitialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
shader->Use();
|
||||||
|
shader->SetParameter( ufm_worldPixelSize, (float) getWorldPixelSize() );
|
||||||
|
shader->Deactivate();
|
||||||
|
|
||||||
// Something betreen BeginDrawing and EndDrawing seems to depend on
|
// Something betreen BeginDrawing and EndDrawing seems to depend on
|
||||||
// this texture unit being active, but it does not assure it itself.
|
// this texture unit being active, but it does not assure it itself.
|
||||||
glActiveTexture( GL_TEXTURE0 );
|
glActiveTexture( GL_TEXTURE0 );
|
||||||
|
@ -516,46 +527,26 @@ void OPENGL_GAL::EndUpdate()
|
||||||
|
|
||||||
void OPENGL_GAL::DrawLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint )
|
void OPENGL_GAL::DrawLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint )
|
||||||
{
|
{
|
||||||
const VECTOR2D startEndVector = aEndPoint - aStartPoint;
|
|
||||||
double lineAngle = startEndVector.Angle();
|
|
||||||
|
|
||||||
currentManager->Color( strokeColor.r, strokeColor.g, strokeColor.b, strokeColor.a );
|
currentManager->Color( strokeColor.r, strokeColor.g, strokeColor.b, strokeColor.a );
|
||||||
|
|
||||||
drawLineQuad( aStartPoint, aEndPoint );
|
drawLineQuad( aStartPoint, aEndPoint );
|
||||||
|
|
||||||
// Line caps
|
|
||||||
if( lineWidth > 1.0 )
|
|
||||||
{
|
|
||||||
drawFilledSemiCircle( aStartPoint, lineWidth / 2, lineAngle + M_PI / 2 );
|
|
||||||
drawFilledSemiCircle( aEndPoint, lineWidth / 2, lineAngle - M_PI / 2 );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void OPENGL_GAL::DrawSegment( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint,
|
void OPENGL_GAL::DrawSegment( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint,
|
||||||
double aWidth )
|
double aWidth )
|
||||||
{
|
{
|
||||||
VECTOR2D startEndVector = aEndPoint - aStartPoint;
|
if( isFillEnabled || aWidth == 1.0 )
|
||||||
double lineAngle = startEndVector.Angle();
|
|
||||||
|
|
||||||
// Width must be nonzero for anything to appear
|
|
||||||
if( aWidth <= 0 )
|
|
||||||
aWidth = 1.0;
|
|
||||||
|
|
||||||
if( isFillEnabled )
|
|
||||||
{
|
{
|
||||||
// Filled tracks
|
|
||||||
currentManager->Color( fillColor.r, fillColor.g, fillColor.b, fillColor.a );
|
currentManager->Color( fillColor.r, fillColor.g, fillColor.b, fillColor.a );
|
||||||
|
|
||||||
SetLineWidth( aWidth );
|
SetLineWidth( aWidth );
|
||||||
drawLineQuad( aStartPoint, aEndPoint );
|
drawLineQuad( aStartPoint, aEndPoint );
|
||||||
|
|
||||||
// Draw line caps
|
|
||||||
drawFilledSemiCircle( aStartPoint, aWidth / 2, lineAngle + M_PI / 2 );
|
|
||||||
drawFilledSemiCircle( aEndPoint, aWidth / 2, lineAngle - M_PI / 2 );
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
auto startEndVector = aEndPoint - aStartPoint;
|
||||||
|
auto lineAngle = startEndVector.Angle();
|
||||||
// Outlined tracks
|
// Outlined tracks
|
||||||
double lineLength = startEndVector.EuclideanNorm();
|
double lineLength = startEndVector.EuclideanNorm();
|
||||||
|
|
||||||
|
@ -1161,7 +1152,7 @@ void OPENGL_GAL::DrawGrid()
|
||||||
compositor->SetBuffer( mainBuffer );
|
compositor->SetBuffer( mainBuffer );
|
||||||
|
|
||||||
// sub-pixel lines all render the same
|
// sub-pixel lines all render the same
|
||||||
double minorLineWidth = std::max( 1.0, gridLineWidth );
|
double minorLineWidth = std::max(1.0, gridLineWidth) * getWorldPixelSize();
|
||||||
double majorLineWidth = minorLineWidth * 2.0;
|
double majorLineWidth = minorLineWidth * 2.0;
|
||||||
|
|
||||||
// Draw the axis and grid
|
// Draw the axis and grid
|
||||||
|
@ -1173,20 +1164,16 @@ void OPENGL_GAL::DrawGrid()
|
||||||
// Draw axes if desired
|
// Draw axes if desired
|
||||||
if( axesEnabled )
|
if( axesEnabled )
|
||||||
{
|
{
|
||||||
glLineWidth( minorLineWidth );
|
SetLineWidth( minorLineWidth );
|
||||||
glColor4d( axesColor.r, axesColor.g, axesColor.b, axesColor.a );
|
SetStrokeColor( axesColor );
|
||||||
|
|
||||||
glBegin( GL_LINES );
|
DrawLine( VECTOR2D( worldStartPoint.x, 0 ), VECTOR2D( worldEndPoint.x, 0 ) );
|
||||||
glVertex2d( worldStartPoint.x, 0 );
|
DrawLine( VECTOR2D( 0, worldStartPoint.y ), VECTOR2D( 0, worldEndPoint.y ) );
|
||||||
glVertex2d( worldEndPoint.x, 0 );
|
|
||||||
glEnd();
|
|
||||||
|
|
||||||
glBegin( GL_LINES );
|
|
||||||
glVertex2d( 0, worldStartPoint.y );
|
|
||||||
glVertex2d( 0, worldEndPoint.y );
|
|
||||||
glEnd();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// force flush
|
||||||
|
nonCachedManager->EndDrawing();
|
||||||
|
|
||||||
if( !gridVisibility )
|
if( !gridVisibility )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -1227,19 +1214,21 @@ void OPENGL_GAL::DrawGrid()
|
||||||
glStencilFunc( GL_ALWAYS, 1, 1 );
|
glStencilFunc( GL_ALWAYS, 1, 1 );
|
||||||
glStencilOp( GL_KEEP, GL_KEEP, GL_INCR );
|
glStencilOp( GL_KEEP, GL_KEEP, GL_INCR );
|
||||||
glColor4d( 0.0, 0.0, 0.0, 0.0 );
|
glColor4d( 0.0, 0.0, 0.0, 0.0 );
|
||||||
|
SetStrokeColor( COLOR4D(0.0, 0.0, 0.0, 0.0 ) );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
glColor4d( gridColor.r, gridColor.g, gridColor.b, gridColor.a );
|
glColor4d( gridColor.r, gridColor.g, gridColor.b, gridColor.a );
|
||||||
|
SetStrokeColor( gridColor );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( gridStyle == GRID_STYLE::SMALL_CROSS )
|
if( gridStyle == GRID_STYLE::SMALL_CROSS )
|
||||||
{
|
{
|
||||||
glLineWidth( minorLineWidth );
|
SetLineWidth( minorLineWidth );
|
||||||
|
|
||||||
// calculate a line len = 2 minorLineWidth, in internal unit value
|
// calculate a line len = 2 minorLineWidth, in internal unit value
|
||||||
// (in fact the size of cross is lineLen*2)
|
// (in fact the size of cross is lineLen*2)
|
||||||
int lineLen = KiROUND( minorLineWidth / worldScale * 2 );
|
int lineLen = KiROUND( minorLineWidth * 2.0 );
|
||||||
|
|
||||||
// Vertical positions
|
// Vertical positions
|
||||||
for( int j = gridStartY; j <= gridEndY; j++ )
|
for( int j = gridStartY; j <= gridEndY; j++ )
|
||||||
|
@ -1257,12 +1246,8 @@ void OPENGL_GAL::DrawGrid()
|
||||||
{
|
{
|
||||||
int posX = i * gridSize.x + gridOrigin.x;
|
int posX = i * gridSize.x + gridOrigin.x;
|
||||||
|
|
||||||
glBegin( GL_LINES );
|
DrawLine( VECTOR2D( posX - lineLen, posY ), VECTOR2D( posX + lineLen, posY ) );
|
||||||
glVertex2d( posX -lineLen, posY );
|
DrawLine( VECTOR2D( posX, posY - lineLen ), VECTOR2D( posX, posY + lineLen ) );
|
||||||
glVertex2d( posX + lineLen, posY );
|
|
||||||
glVertex2d( posX, posY - lineLen );
|
|
||||||
glVertex2d( posX, posY + lineLen );
|
|
||||||
glEnd();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1280,24 +1265,27 @@ void OPENGL_GAL::DrawGrid()
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if( j % gridTick == 0 && gridScreenSizeDense > gridThreshold )
|
if( j % gridTick == 0 && gridScreenSizeDense > gridThreshold )
|
||||||
glLineWidth( majorLineWidth );
|
SetLineWidth( majorLineWidth );
|
||||||
else
|
else
|
||||||
glLineWidth( minorLineWidth );
|
SetLineWidth( minorLineWidth );
|
||||||
|
|
||||||
if( ( j % gridTick == 0 && gridScreenSizeCoarse > gridThreshold )
|
if( ( j % gridTick == 0 && gridScreenSizeCoarse > gridThreshold )
|
||||||
|| gridScreenSizeDense > gridThreshold )
|
|| gridScreenSizeDense > gridThreshold )
|
||||||
{
|
{
|
||||||
glBegin( GL_LINES );
|
VECTOR2D a ( gridStartX * gridSize.x + gridOrigin.x, y );
|
||||||
glVertex2d( gridStartX * gridSize.x + gridOrigin.x, y );
|
VECTOR2D b ( gridEndX * gridSize.x + gridOrigin.x, y );
|
||||||
glVertex2d( gridEndX * gridSize.x + gridOrigin.x, y );
|
|
||||||
glEnd();
|
DrawLine( a, b );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nonCachedManager->EndDrawing();
|
||||||
|
|
||||||
if( gridStyle == GRID_STYLE::DOTS )
|
if( gridStyle == GRID_STYLE::DOTS )
|
||||||
{
|
{
|
||||||
glStencilFunc( GL_NOTEQUAL, 0, 1 );
|
glStencilFunc( GL_NOTEQUAL, 0, 1 );
|
||||||
glColor4d( gridColor.r, gridColor.g, gridColor.b, gridColor.a );
|
glColor4d( gridColor.r, gridColor.g, gridColor.b, gridColor.a );
|
||||||
|
SetStrokeColor( gridColor );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Horizontal lines
|
// Horizontal lines
|
||||||
|
@ -1310,20 +1298,21 @@ void OPENGL_GAL::DrawGrid()
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if( i % gridTick == 0 && gridScreenSizeDense > gridThreshold )
|
if( i % gridTick == 0 && gridScreenSizeDense > gridThreshold )
|
||||||
glLineWidth( majorLineWidth );
|
SetLineWidth( majorLineWidth );
|
||||||
else
|
else
|
||||||
glLineWidth( minorLineWidth );
|
SetLineWidth( minorLineWidth );
|
||||||
|
|
||||||
if( ( i % gridTick == 0 && gridScreenSizeCoarse > gridThreshold )
|
if( ( i % gridTick == 0 && gridScreenSizeCoarse > gridThreshold )
|
||||||
|| gridScreenSizeDense > gridThreshold )
|
|| gridScreenSizeDense > gridThreshold )
|
||||||
{
|
{
|
||||||
glBegin( GL_LINES );
|
VECTOR2D a ( x, gridStartY * gridSize.y + gridOrigin.y );
|
||||||
glVertex2d( x, gridStartY * gridSize.y + gridOrigin.y );
|
VECTOR2D b ( x, gridEndY * gridSize.y + gridOrigin.y );
|
||||||
glVertex2d( x, gridEndY * gridSize.y + gridOrigin.y );
|
DrawLine( a, b );
|
||||||
glEnd();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nonCachedManager->EndDrawing();
|
||||||
|
|
||||||
if( gridStyle == GRID_STYLE::DOTS )
|
if( gridStyle == GRID_STYLE::DOTS )
|
||||||
glDisable( GL_STENCIL_TEST );
|
glDisable( GL_STENCIL_TEST );
|
||||||
}
|
}
|
||||||
|
@ -1576,38 +1565,47 @@ void OPENGL_GAL::drawLineQuad( const VECTOR2D& aStartPoint, const VECTOR2D& aEnd
|
||||||
* dots mark triangles' hypotenuses
|
* dots mark triangles' hypotenuses
|
||||||
*/
|
*/
|
||||||
|
|
||||||
VECTOR2D startEndVector = aEndPoint - aStartPoint;
|
auto v1 = currentManager->GetTransformation() * glm::vec4( aStartPoint.x, aStartPoint.y, 0.0, 0.0 );
|
||||||
double lineLength = startEndVector.EuclideanNorm();
|
auto v2 = currentManager->GetTransformation() * glm::vec4( aEndPoint.x, aEndPoint.y, 0.0, 0.0 );
|
||||||
|
|
||||||
if( lineLength <= 0.0 )
|
VECTOR2D startEndVector( v2.x - v1.x, v2.y - v1.y );
|
||||||
return;
|
|
||||||
|
|
||||||
double scale = 0.5 * lineWidth / lineLength;
|
double lineLength = startEndVector.EuclideanNorm();
|
||||||
|
|
||||||
// The perpendicular vector also needs transformations
|
VECTOR2D vs ( startEndVector );
|
||||||
glm::vec4 vector = currentManager->GetTransformation() *
|
float aspect;
|
||||||
glm::vec4( -startEndVector.y * scale, startEndVector.x * scale, 0.0, 0.0 );
|
|
||||||
|
if ( lineWidth == 0.0 ) // pixel-width line
|
||||||
|
{
|
||||||
|
vs = vs.Resize( 0.5 );
|
||||||
|
aspect = ( lineLength + 1.0 );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
vs = vs.Resize( 0.5 * lineWidth );
|
||||||
|
aspect = ( lineLength + lineWidth ) / lineWidth;
|
||||||
|
}
|
||||||
|
|
||||||
currentManager->Reserve( 6 );
|
currentManager->Reserve( 6 );
|
||||||
|
|
||||||
// Line width is maintained by the vertex shader
|
// Line width is maintained by the vertex shader
|
||||||
currentManager->Shader( SHADER_LINE, vector.x, vector.y, lineWidth );
|
currentManager->Shader( SHADER_LINE_A, aspect, vs.x, vs.y );
|
||||||
currentManager->Vertex( aStartPoint.x, aStartPoint.y, layerDepth ); // v0
|
currentManager->Vertex( aStartPoint, layerDepth );
|
||||||
|
|
||||||
currentManager->Shader( SHADER_LINE, -vector.x, -vector.y, lineWidth );
|
currentManager->Shader( SHADER_LINE_B, aspect, vs.x, vs.y );
|
||||||
currentManager->Vertex( aStartPoint.x, aStartPoint.y, layerDepth ); // v1
|
currentManager->Vertex( aStartPoint, layerDepth );
|
||||||
|
|
||||||
currentManager->Shader( SHADER_LINE, -vector.x, -vector.y, lineWidth );
|
currentManager->Shader( SHADER_LINE_C, aspect, vs.x, vs.y );
|
||||||
currentManager->Vertex( aEndPoint.x, aEndPoint.y, layerDepth ); // v3
|
currentManager->Vertex( aEndPoint, layerDepth );
|
||||||
|
|
||||||
currentManager->Shader( SHADER_LINE, vector.x, vector.y, lineWidth );
|
currentManager->Shader( SHADER_LINE_D, aspect, vs.x, vs.y );
|
||||||
currentManager->Vertex( aStartPoint.x, aStartPoint.y, layerDepth ); // v0
|
currentManager->Vertex( aEndPoint, layerDepth );
|
||||||
|
|
||||||
currentManager->Shader( SHADER_LINE, -vector.x, -vector.y, lineWidth );
|
currentManager->Shader( SHADER_LINE_E, aspect, vs.x, vs.y );
|
||||||
currentManager->Vertex( aEndPoint.x, aEndPoint.y, layerDepth ); // v3
|
currentManager->Vertex( aEndPoint, layerDepth );
|
||||||
|
|
||||||
currentManager->Shader( SHADER_LINE, vector.x, vector.y, lineWidth );
|
currentManager->Shader( SHADER_LINE_F, aspect, vs.x, vs.y );
|
||||||
currentManager->Vertex( aEndPoint.x, aEndPoint.y, layerDepth ); // v2
|
currentManager->Vertex( aStartPoint, layerDepth );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -328,6 +328,7 @@ private:
|
||||||
bool isInitialized; ///< Basic initialization flag, has to be done
|
bool isInitialized; ///< Basic initialization flag, has to be done
|
||||||
///< when the window is visible
|
///< when the window is visible
|
||||||
bool isGrouping; ///< Was a group started?
|
bool isGrouping; ///< Was a group started?
|
||||||
|
GLint ufm_worldPixelSize;
|
||||||
|
|
||||||
std::unique_ptr<GL_BITMAP_CACHE> bitmapCache;
|
std::unique_ptr<GL_BITMAP_CACHE> bitmapCache;
|
||||||
|
|
||||||
|
@ -465,6 +466,8 @@ private:
|
||||||
return std::min( 1e6 / aRadius, 2.0 * M_PI / CIRCLE_POINTS );
|
return std::min( 1e6 / aRadius, 2.0 * M_PI / CIRCLE_POINTS );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double getWorldPixelSize() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Basic OpenGL initialization.
|
* @brief Basic OpenGL initialization.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -30,20 +30,26 @@
|
||||||
#ifndef VERTEX_COMMON_H_
|
#ifndef VERTEX_COMMON_H_
|
||||||
#define VERTEX_COMMON_H_
|
#define VERTEX_COMMON_H_
|
||||||
|
|
||||||
|
#include <math/vector2d.h>
|
||||||
#include <GL/glew.h>
|
#include <GL/glew.h>
|
||||||
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
|
||||||
namespace KIGFX
|
namespace KIGFX
|
||||||
{
|
{
|
||||||
///> Possible types of shaders
|
///> Possible types of shaders (keep consistent with the actual shader source in gl_builtin_shaders.cpp)
|
||||||
enum SHADER_MODE
|
enum SHADER_MODE
|
||||||
{
|
{
|
||||||
SHADER_NONE = 0,
|
SHADER_NONE = 0,
|
||||||
SHADER_LINE,
|
SHADER_FILLED_CIRCLE = 2,
|
||||||
SHADER_FILLED_CIRCLE,
|
SHADER_STROKED_CIRCLE = 3,
|
||||||
SHADER_STROKED_CIRCLE,
|
SHADER_FONT = 4,
|
||||||
SHADER_FONT
|
SHADER_LINE_A = 5,
|
||||||
|
SHADER_LINE_B = 6,
|
||||||
|
SHADER_LINE_C = 7,
|
||||||
|
SHADER_LINE_D = 8,
|
||||||
|
SHADER_LINE_E = 9,
|
||||||
|
SHADER_LINE_F = 10
|
||||||
};
|
};
|
||||||
|
|
||||||
///> Data structure for vertices {X,Y,Z,R,G,B,A,shader¶m}
|
///> Data structure for vertices {X,Y,Z,R,G,B,A,shader¶m}
|
||||||
|
|
|
@ -106,6 +106,20 @@ public:
|
||||||
*/
|
*/
|
||||||
bool Vertex( GLfloat aX, GLfloat aY, GLfloat aZ );
|
bool Vertex( GLfloat aX, GLfloat aY, GLfloat aZ );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function Vertex()
|
||||||
|
* adds a vertex with the given coordinates to the currently set item. Vertex coordinates will
|
||||||
|
* have the current transformation matrix applied.
|
||||||
|
*
|
||||||
|
* @param aXY are the XY coordinates of the new vertex.
|
||||||
|
* @param aZ is the Z coordinate of the new vertex.
|
||||||
|
* @return True if successful, false otherwise.
|
||||||
|
*/
|
||||||
|
bool Vertex( const VECTOR2D& aXY, GLfloat aZ )
|
||||||
|
{
|
||||||
|
return Vertex( aXY.x, aXY.y, aZ );
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function Vertices()
|
* Function Vertices()
|
||||||
* adds one or more vertices to the currently set item. It takes advantage of allocating memory
|
* adds one or more vertices to the currently set item. It takes advantage of allocating memory
|
||||||
|
@ -163,10 +177,10 @@ public:
|
||||||
* @param aParam2 is the optional parameter for a shader.
|
* @param aParam2 is the optional parameter for a shader.
|
||||||
* @param aParam3 is the optional parameter for a shader.
|
* @param aParam3 is the optional parameter for a shader.
|
||||||
*/
|
*/
|
||||||
inline void Shader( GLfloat aShaderType, GLfloat aParam1 = 0.0f,
|
inline void Shader( int aShaderType, GLfloat aParam1 = 0.0f,
|
||||||
GLfloat aParam2 = 0.0f, GLfloat aParam3 = 0.0f )
|
GLfloat aParam2 = 0.0f, GLfloat aParam3 = 0.0f )
|
||||||
{
|
{
|
||||||
m_shader[0] = aShaderType;
|
m_shader[0] = (float) aShaderType;
|
||||||
m_shader[1] = aParam1;
|
m_shader[1] = aParam1;
|
||||||
m_shader[2] = aParam2;
|
m_shader[2] = aParam2;
|
||||||
m_shader[3] = aParam3;
|
m_shader[3] = aParam3;
|
||||||
|
|
Loading…
Reference in New Issue