Initial implementation of shader translation to cpp at build time
This commit is contained in:
parent
f4f3638103
commit
6188f632b9
|
@ -0,0 +1,35 @@
|
|||
file( READ ${SOURCE} SOURCE_TEXT )
|
||||
|
||||
set( outCppText
|
||||
"
|
||||
#include <${OUTHEADERFILE}>
|
||||
|
||||
namespace KIGFX {
|
||||
namespace BUILTIN_SHADERS {
|
||||
const char ${OUTVARNAME}[] = R\"SHADER_SOURCE(
|
||||
${SOURCE_TEXT}
|
||||
)SHADER_SOURCE\";
|
||||
}
|
||||
}
|
||||
" )
|
||||
|
||||
file(
|
||||
WRITE ${DESTINATION_SOURCE_DIR}/${OUTCPPFILE}
|
||||
"${outCppText}"
|
||||
)
|
||||
|
||||
|
||||
set( outHeaderText
|
||||
"namespace KIGFX {
|
||||
namespace BUILTIN_SHADERS {
|
||||
extern const char ${OUTVARNAME}[];
|
||||
}
|
||||
}"
|
||||
)
|
||||
|
||||
file(
|
||||
WRITE ${DESTINATION_HEADER_DIR}/${OUTHEADERFILE}
|
||||
"${outHeaderText}"
|
||||
)
|
||||
|
||||
message(STATUS "Shader ${SOURCE} converted to ${DESTINATION_SOURCE_DIR}/${OUTCPPFILE}")
|
|
@ -1,7 +1,7 @@
|
|||
|
||||
set( GAL_SRCS
|
||||
# Common part
|
||||
../callback_gal.cpp
|
||||
../callback_gal.cpp
|
||||
../draw_panel_gal.cpp
|
||||
../gl_context_mgr.cpp
|
||||
../newstroke_font.cpp
|
||||
|
@ -52,9 +52,33 @@ target_link_libraries( gal
|
|||
${PIXMAN_LIBRARIES}
|
||||
${OPENGL_LIBRARIES}
|
||||
${GDI_PLUS_LIBRARIES}
|
||||
# outline font support
|
||||
${FREETYPE_LIBRARIES}
|
||||
${HarfBuzz_LIBRARIES}
|
||||
${Fontconfig_LIBRARIES}
|
||||
# outline font support
|
||||
${FREETYPE_LIBRARIES}
|
||||
${HarfBuzz_LIBRARIES}
|
||||
${Fontconfig_LIBRARIES}
|
||||
)
|
||||
function( add_shader outTarget inFile shaderName )
|
||||
set(outCppName "${shaderName}.cpp")
|
||||
set(outHeaderName "${shaderName}.h")
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${outCppName}
|
||||
${CMAKE_BINARY_DIR}/include/gal/shaders/${outHeaderName}
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
-DSOURCE="${CMAKE_CURRENT_SOURCE_DIR}/shaders/${inFile}"
|
||||
-DDESTINATION_SOURCE_DIR="${CMAKE_CURRENT_BINARY_DIR}/"
|
||||
-DDESTINATION_HEADER_DIR="${CMAKE_BINARY_DIR}/include/gal/shaders/"
|
||||
-DOUTCPPFILE="${outCppName}"
|
||||
-DOUTHEADERFILE="${outHeaderName}"
|
||||
-DOUTVARNAME="${shaderName}_shader"
|
||||
-P ${CMAKE_MODULE_PATH}/BuildSteps/CreateShaderCpp.cmake
|
||||
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/shaders/${inFile}
|
||||
${CMAKE_MODULE_PATH}/BuildSteps/CreateShaderCpp.cmake
|
||||
)
|
||||
|
||||
target_sources( ${outTarget} PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/${outCppName} )
|
||||
target_include_directories( ${outTarget} PUBLIC ${CMAKE_BINARY_DIR}/include/gal/shaders/ )
|
||||
endfunction()
|
||||
|
||||
add_shader( gal kicad_frag.glsl glsl_kicad_frag )
|
||||
add_shader( gal kicad_vert.glsl glsl_kicad_vert )
|
|
@ -26,392 +26,6 @@
|
|||
namespace KIGFX {
|
||||
namespace BUILTIN_SHADERS {
|
||||
|
||||
/*
|
||||
*
|
||||
* KiCad shaders
|
||||
*
|
||||
*/
|
||||
|
||||
const char kicad_vertex_shader[] = R"SHADER_SOURCE(
|
||||
|
||||
/*
|
||||
* This program source code file is part of KICAD, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2013-2016 CERN
|
||||
* @author Maciej Suminski <maciej.suminski@cern.ch>
|
||||
*
|
||||
* Vertex shader
|
||||
*
|
||||
* This program 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 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program 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 for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#version 120
|
||||
|
||||
// Shader types
|
||||
const float SHADER_FILLED_CIRCLE = 2.0;
|
||||
const float SHADER_STROKED_CIRCLE = 3.0;
|
||||
const float SHADER_FONT = 4.0;
|
||||
const float SHADER_LINE_A = 5.0;
|
||||
const float SHADER_LINE_B = 6.0;
|
||||
const float SHADER_LINE_C = 7.0;
|
||||
const float SHADER_LINE_D = 8.0;
|
||||
const float SHADER_LINE_E = 9.0;
|
||||
const float SHADER_LINE_F = 10.0;
|
||||
|
||||
// Minimum line width
|
||||
const float MIN_WIDTH = 1.0;
|
||||
|
||||
attribute vec4 attrShaderParams;
|
||||
varying vec4 shaderParams;
|
||||
varying vec2 circleCoords;
|
||||
uniform float worldPixelSize;
|
||||
uniform vec2 screenPixelSize;
|
||||
uniform float pixelSizeMultiplier;
|
||||
uniform float minLinePixelWidth;
|
||||
uniform vec2 antialiasingOffset;
|
||||
|
||||
|
||||
float roundr( float f, float r )
|
||||
{
|
||||
return floor(f / r + 0.5) * r;
|
||||
}
|
||||
|
||||
vec4 roundv( vec4 x, vec2 t)
|
||||
{
|
||||
return vec4( roundr(x.x, t.x), roundr(x.y, t.y), x.z, x.w );
|
||||
}
|
||||
|
||||
void computeLineCoords( bool posture, vec2 vs, vec2 vp, vec2 texcoord, vec2 dir, float lineWidth, bool endV )
|
||||
{
|
||||
float lineLength = length(vs);
|
||||
vec4 screenPos = gl_ModelViewProjectionMatrix * gl_Vertex + vec4(1, 1, 0, 0);
|
||||
float w = ((lineWidth == 0.0) ? worldPixelSize : lineWidth );
|
||||
float pixelWidth = roundr( w / worldPixelSize, 1.0 );
|
||||
float aspect = ( lineLength + w ) / w;
|
||||
vec4 color = gl_Color;
|
||||
vec2 s = sign( vec2( gl_ModelViewProjectionMatrix[0][0], gl_ModelViewProjectionMatrix[1][1] ) );
|
||||
|
||||
|
||||
if( pixelWidth < 1.0 )
|
||||
pixelWidth = 1.0;
|
||||
|
||||
if ( pixelWidth > 1.0 || pixelSizeMultiplier > 1.0 )
|
||||
{
|
||||
vec2 offsetNorm = (vs + vp) * pixelWidth / lineLength * 0.5;
|
||||
vec4 screenOffset = vec4( s.x * offsetNorm.x * screenPixelSize.x, s.y * offsetNorm.y * screenPixelSize.y , 0, 0);
|
||||
vec4 adjust = vec4(-1, -1, 0, 0);
|
||||
|
||||
if( mod( pixelWidth * pixelSizeMultiplier, 2.0 ) > 0.9 )
|
||||
{
|
||||
adjust += vec4( screenPixelSize.x, screenPixelSize.y, 0, 0 ) * 0.5;
|
||||
}
|
||||
|
||||
gl_Position = roundv(screenPos, screenPixelSize) + adjust + screenOffset;
|
||||
|
||||
shaderParams[0] = SHADER_LINE_A;
|
||||
}
|
||||
else {
|
||||
vec4 pos0 = screenPos;
|
||||
pos0.xy += ( posture ? dir.xy : dir.yx ) * screenPixelSize / 2.0;
|
||||
|
||||
if(posture)
|
||||
{
|
||||
pos0.y -= screenPixelSize.y * sign(vs.y) * 0.5;
|
||||
}
|
||||
else
|
||||
{
|
||||
pos0.x += screenPixelSize.x * sign(vs.x) * 0.5;
|
||||
}
|
||||
|
||||
gl_Position = pos0 - vec4(1, 1, 0, 0);
|
||||
shaderParams[0] = SHADER_LINE_B;
|
||||
}
|
||||
|
||||
shaderParams[1] = aspect;
|
||||
|
||||
gl_TexCoord[0].st = vec2(aspect * texcoord.x, texcoord.y);
|
||||
gl_FrontColor = gl_Color;
|
||||
}
|
||||
|
||||
|
||||
void computeCircleCoords( float mode, float vertexIndex, float radius, float lineWidth )
|
||||
{
|
||||
vec4 delta;
|
||||
vec4 center = roundv( gl_ModelViewProjectionMatrix * gl_Vertex + vec4(1, 1, 0, 0), screenPixelSize );
|
||||
float pixelWidth = roundr( lineWidth / worldPixelSize, 1.0);
|
||||
float pixelR = roundr( radius / worldPixelSize, 1.0);
|
||||
|
||||
if( mode == SHADER_STROKED_CIRCLE)
|
||||
pixelR += pixelWidth / 2.0;
|
||||
|
||||
vec4 adjust = vec4(-1, -1, 0, 0);
|
||||
|
||||
if( pixelWidth < 1.0 )
|
||||
pixelWidth = 1.0;
|
||||
|
||||
if( vertexIndex == 1.0 )
|
||||
{
|
||||
circleCoords = vec2( -sqrt( 3.0 ), -1.0 );
|
||||
delta = vec4( -pixelR * sqrt(3.0), -pixelR, 0, 0 );
|
||||
}
|
||||
else if( vertexIndex == 2.0 )
|
||||
{
|
||||
circleCoords = vec2( sqrt( 3.0 ), -1.0 );
|
||||
delta = vec4( pixelR * sqrt( 3.0 ), -pixelR, 0, 0 );
|
||||
}
|
||||
else if( vertexIndex == 3.0 )
|
||||
{
|
||||
circleCoords = vec2( 0.0, 2.0 );
|
||||
delta = vec4( 0, 2 * pixelR, 0, 0 );
|
||||
}
|
||||
else if( vertexIndex == 4.0 )
|
||||
{
|
||||
circleCoords = vec2( -sqrt( 3.0 ), 0.0 );
|
||||
delta = vec4( 0, 0, 0, 0 );
|
||||
}
|
||||
else if( vertexIndex == 5.0 )
|
||||
{
|
||||
circleCoords = vec2( sqrt( 3.0 ), 0.0 );
|
||||
delta = vec4( 0, 0, 0, 0 );
|
||||
}
|
||||
else if( vertexIndex == 6.0 )
|
||||
{
|
||||
circleCoords = vec2( 0.0, 2.0 );
|
||||
delta = vec4( 0, 0, 0, 0 );
|
||||
}
|
||||
|
||||
shaderParams[2] = pixelR;
|
||||
shaderParams[3] = pixelWidth;
|
||||
|
||||
delta.x *= screenPixelSize.x;
|
||||
delta.y *= screenPixelSize.y;
|
||||
|
||||
gl_Position = center + delta + adjust;
|
||||
gl_FrontColor = gl_Color;
|
||||
}
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
float mode = attrShaderParams[0];
|
||||
|
||||
// Pass attributes to the fragment shader
|
||||
shaderParams = attrShaderParams;
|
||||
|
||||
float lineWidth = shaderParams.y;
|
||||
vec2 vs = shaderParams.zw;
|
||||
vec2 vp = vec2(-vs.y, vs.x);
|
||||
bool posture = abs( vs.x ) < abs(vs.y);
|
||||
|
||||
if( mode == SHADER_LINE_A )
|
||||
computeLineCoords( posture, -vs, vp, vec2( -1, -1 ), vec2( -1, 0 ), lineWidth, false );
|
||||
else if( mode == SHADER_LINE_B )
|
||||
computeLineCoords( posture, -vs, -vp, vec2( -1, 1 ), vec2( 1, 0 ), lineWidth, false );
|
||||
else if( mode == SHADER_LINE_C )
|
||||
computeLineCoords( posture, vs, -vp, vec2( 1, 1 ), vec2( 1, 0 ), lineWidth, true );
|
||||
else if( mode == SHADER_LINE_D )
|
||||
computeLineCoords( posture, vs, -vp, vec2( -1, -1 ), vec2( 1, 0 ), lineWidth, true );
|
||||
else if( mode == SHADER_LINE_E )
|
||||
computeLineCoords( posture, vs, vp, vec2( -1, 1 ), vec2( -1, 0 ), lineWidth, true );
|
||||
else if( mode == SHADER_LINE_F )
|
||||
computeLineCoords( posture, -vs, vp, vec2( 1, 1 ), vec2( -1, 0 ), lineWidth, false );
|
||||
else if( mode == SHADER_FILLED_CIRCLE || mode == SHADER_STROKED_CIRCLE)
|
||||
computeCircleCoords( mode, shaderParams.y, shaderParams.z, shaderParams.w );
|
||||
else
|
||||
{
|
||||
// Pass through the coordinates like in the fixed pipeline
|
||||
gl_Position = ftransform();
|
||||
gl_FrontColor = gl_Color;
|
||||
|
||||
}
|
||||
|
||||
gl_Position.xy += antialiasingOffset;
|
||||
}
|
||||
|
||||
)SHADER_SOURCE";
|
||||
|
||||
const char kicad_fragment_shader[] = R"SHADER_SOURCE(
|
||||
|
||||
/*
|
||||
* This program source code file is part of KICAD, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2013-2016 CERN
|
||||
* Copyright (C) 2016 Kicad Developers, see authors.txt for contributors.
|
||||
* @author Maciej Suminski <maciej.suminski@cern.ch>
|
||||
*
|
||||
* Fragment shader
|
||||
*
|
||||
* This program 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 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program 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 for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#version 120
|
||||
|
||||
// Multi-channel signed distance field
|
||||
#define USE_MSDF
|
||||
|
||||
// Shader types
|
||||
const float SHADER_FILLED_CIRCLE = 2.0;
|
||||
const float SHADER_STROKED_CIRCLE = 3.0;
|
||||
const float SHADER_FONT = 4.0;
|
||||
const float SHADER_LINE_A = 5.0;
|
||||
|
||||
varying vec4 shaderParams;
|
||||
varying vec2 circleCoords;
|
||||
uniform sampler2D fontTexture;
|
||||
uniform float worldPixelSize;
|
||||
|
||||
// Needed to reconstruct the mipmap level / texel derivative
|
||||
uniform int fontTextureWidth;
|
||||
|
||||
void filledCircle( vec2 aCoord )
|
||||
{
|
||||
if( dot( aCoord, aCoord ) < 1.0 )
|
||||
gl_FragColor = gl_Color;
|
||||
else
|
||||
discard;
|
||||
}
|
||||
|
||||
float pixelSegDistance( vec2 aCoord )
|
||||
{
|
||||
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 )
|
||||
{
|
||||
float outerRadius = max( aRadius, 0.0 );
|
||||
float innerRadius = max( aRadius - aWidth, 0.0 );
|
||||
|
||||
if( ( dot( aCoord, aCoord ) < 1.0 ) &&
|
||||
( dot( aCoord, aCoord ) * ( outerRadius * outerRadius ) > innerRadius * innerRadius ) )
|
||||
gl_FragColor = gl_Color;
|
||||
else
|
||||
discard;
|
||||
}
|
||||
|
||||
|
||||
void drawLine( vec2 aCoord )
|
||||
{
|
||||
if( isPixelInSegment( aCoord ) != 0)
|
||||
gl_FragColor = gl_Color;
|
||||
else
|
||||
discard;
|
||||
}
|
||||
|
||||
#ifdef USE_MSDF
|
||||
float median( vec3 v )
|
||||
{
|
||||
return max( min( v.r, v.g ), min( max( v.r, v.g ), v.b ) );
|
||||
}
|
||||
#endif
|
||||
|
||||
void main()
|
||||
{
|
||||
// VS to FS pipeline does math that means we can't rely on the mode
|
||||
// parameter being bit-exact without rounding it first.
|
||||
float mode = floor( shaderParams[0] + 0.5 );
|
||||
|
||||
if( mode == SHADER_LINE_A )
|
||||
{
|
||||
drawLine( gl_TexCoord[0].st );
|
||||
}
|
||||
else if( mode == SHADER_FILLED_CIRCLE )
|
||||
{
|
||||
filledCircle( circleCoords );
|
||||
}
|
||||
else if( mode == SHADER_STROKED_CIRCLE )
|
||||
{
|
||||
strokedCircle( circleCoords, shaderParams[2], shaderParams[3] );
|
||||
}
|
||||
else if( mode == SHADER_FONT )
|
||||
{
|
||||
vec2 tex = shaderParams.yz;
|
||||
|
||||
// Unless we're stretching chars it is okay to consider
|
||||
// one derivative for filtering
|
||||
float derivative = length( dFdx( tex ) ) * fontTextureWidth / 4;
|
||||
|
||||
#ifdef USE_MSDF
|
||||
float dist = median( texture2D( fontTexture, tex ).rgb );
|
||||
#else
|
||||
float dist = texture2D( fontTexture, tex ).r;
|
||||
#endif
|
||||
|
||||
// use the derivative for zoom-adaptive filtering
|
||||
float alpha = smoothstep( 0.5 - derivative, 0.5 + derivative, dist ) * gl_Color.a;
|
||||
|
||||
gl_FragColor = vec4( gl_Color.rgb, alpha );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Simple pass-through
|
||||
gl_FragColor = gl_Color;
|
||||
}
|
||||
}
|
||||
|
||||
)SHADER_SOURCE";
|
||||
|
||||
const char ssaa_x4_vertex_shader[] = R"SHADER_SOURCE(
|
||||
|
||||
#version 120
|
||||
varying vec2 texcoord;
|
||||
void main()
|
||||
{
|
||||
texcoord = gl_MultiTexCoord0.st;
|
||||
gl_Position = ftransform();
|
||||
}
|
||||
|
||||
)SHADER_SOURCE";
|
||||
|
||||
const char ssaa_x4_fragment_shader[] = R"SHADER_SOURCE(
|
||||
|
||||
#version 120
|
||||
|
|
|
@ -28,9 +28,6 @@ namespace KIGFX {
|
|||
|
||||
namespace BUILTIN_SHADERS {
|
||||
|
||||
extern const char kicad_vertex_shader[];
|
||||
extern const char kicad_fragment_shader[];
|
||||
|
||||
extern const char ssaa_x4_vertex_shader[];
|
||||
extern const char ssaa_x4_fragment_shader[];
|
||||
|
||||
|
|
|
@ -72,7 +72,8 @@ using namespace KIGFX;
|
|||
// The current font is "Ubuntu Mono" available under Ubuntu Font Licence 1.0
|
||||
// (see ubuntu-font-licence-1.0.txt for details)
|
||||
#include "gl_resources.h"
|
||||
#include "gl_builtin_shaders.h"
|
||||
#include <glsl_kicad_frag.h>
|
||||
#include <glsl_kicad_vert.h>
|
||||
using namespace KIGFX::BUILTIN_FONT;
|
||||
|
||||
static void InitTesselatorCallbacks( GLUtesselator* aTesselator );
|
||||
|
@ -2302,14 +2303,14 @@ void OPENGL_GAL::init()
|
|||
// Prepare shaders
|
||||
if( !m_shader->IsLinked()
|
||||
&& !m_shader->LoadShaderFromStrings( SHADER_TYPE_VERTEX,
|
||||
BUILTIN_SHADERS::kicad_vertex_shader ) )
|
||||
BUILTIN_SHADERS::glsl_kicad_vert_shader ) )
|
||||
{
|
||||
throw std::runtime_error( "Cannot compile vertex shader!" );
|
||||
}
|
||||
|
||||
if( !m_shader->IsLinked()
|
||||
&& !m_shader->LoadShaderFromStrings( SHADER_TYPE_FRAGMENT,
|
||||
BUILTIN_SHADERS::kicad_fragment_shader ) )
|
||||
BUILTIN_SHADERS::glsl_kicad_frag_shader ) )
|
||||
{
|
||||
throw std::runtime_error( "Cannot compile fragment shader!" );
|
||||
}
|
||||
|
|
|
@ -0,0 +1,150 @@
|
|||
/*
|
||||
* This program source code file is part of KICAD, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2013-2016 CERN
|
||||
* Copyright (C) 2016 Kicad Developers, see authors.txt for contributors.
|
||||
* @author Maciej Suminski <maciej.suminski@cern.ch>
|
||||
*
|
||||
* Fragment shader
|
||||
*
|
||||
* This program 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 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program 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 for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#version 120
|
||||
|
||||
// Multi-channel signed distance field
|
||||
#define USE_MSDF
|
||||
|
||||
// Shader types
|
||||
const float SHADER_FILLED_CIRCLE = 2.0;
|
||||
const float SHADER_STROKED_CIRCLE = 3.0;
|
||||
const float SHADER_FONT = 4.0;
|
||||
const float SHADER_LINE_A = 5.0;
|
||||
|
||||
varying vec4 shaderParams;
|
||||
varying vec2 circleCoords;
|
||||
uniform sampler2D fontTexture;
|
||||
uniform float worldPixelSize;
|
||||
|
||||
// Needed to reconstruct the mipmap level / texel derivative
|
||||
uniform int fontTextureWidth;
|
||||
|
||||
void filledCircle( vec2 aCoord )
|
||||
{
|
||||
if( dot( aCoord, aCoord ) < 1.0 )
|
||||
gl_FragColor = gl_Color;
|
||||
else
|
||||
discard;
|
||||
}
|
||||
|
||||
float pixelSegDistance( vec2 aCoord )
|
||||
{
|
||||
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 )
|
||||
{
|
||||
float outerRadius = max( aRadius, 0.0 );
|
||||
float innerRadius = max( aRadius - aWidth, 0.0 );
|
||||
|
||||
if( ( dot( aCoord, aCoord ) < 1.0 ) &&
|
||||
( dot( aCoord, aCoord ) * ( outerRadius * outerRadius ) > innerRadius * innerRadius ) )
|
||||
gl_FragColor = gl_Color;
|
||||
else
|
||||
discard;
|
||||
}
|
||||
|
||||
|
||||
void drawLine( vec2 aCoord )
|
||||
{
|
||||
if( isPixelInSegment( aCoord ) != 0)
|
||||
gl_FragColor = gl_Color;
|
||||
else
|
||||
discard;
|
||||
}
|
||||
|
||||
#ifdef USE_MSDF
|
||||
float median( vec3 v )
|
||||
{
|
||||
return max( min( v.r, v.g ), min( max( v.r, v.g ), v.b ) );
|
||||
}
|
||||
#endif
|
||||
|
||||
void main()
|
||||
{
|
||||
// VS to FS pipeline does math that means we can't rely on the mode
|
||||
// parameter being bit-exact without rounding it first.
|
||||
float mode = floor( shaderParams[0] + 0.5 );
|
||||
|
||||
if( mode == SHADER_LINE_A )
|
||||
{
|
||||
drawLine( gl_TexCoord[0].st );
|
||||
}
|
||||
else if( mode == SHADER_FILLED_CIRCLE )
|
||||
{
|
||||
filledCircle( circleCoords );
|
||||
}
|
||||
else if( mode == SHADER_STROKED_CIRCLE )
|
||||
{
|
||||
strokedCircle( circleCoords, shaderParams[2], shaderParams[3] );
|
||||
}
|
||||
else if( mode == SHADER_FONT )
|
||||
{
|
||||
vec2 tex = shaderParams.yz;
|
||||
|
||||
// Unless we're stretching chars it is okay to consider
|
||||
// one derivative for filtering
|
||||
float derivative = length( dFdx( tex ) ) * fontTextureWidth / 4;
|
||||
|
||||
#ifdef USE_MSDF
|
||||
float dist = median( texture2D( fontTexture, tex ).rgb );
|
||||
#else
|
||||
float dist = texture2D( fontTexture, tex ).r;
|
||||
#endif
|
||||
|
||||
// use the derivative for zoom-adaptive filtering
|
||||
float alpha = smoothstep( 0.5 - derivative, 0.5 + derivative, dist ) * gl_Color.a;
|
||||
|
||||
gl_FragColor = vec4( gl_Color.rgb, alpha );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Simple pass-through
|
||||
gl_FragColor = gl_Color;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,208 @@
|
|||
/*
|
||||
* This program source code file is part of KICAD, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2013-2016 CERN
|
||||
* @author Maciej Suminski <maciej.suminski@cern.ch>
|
||||
*
|
||||
* Vertex shader
|
||||
*
|
||||
* This program 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 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program 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 for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#version 120
|
||||
|
||||
// Shader types
|
||||
const float SHADER_FILLED_CIRCLE = 2.0;
|
||||
const float SHADER_STROKED_CIRCLE = 3.0;
|
||||
const float SHADER_FONT = 4.0;
|
||||
const float SHADER_LINE_A = 5.0;
|
||||
const float SHADER_LINE_B = 6.0;
|
||||
const float SHADER_LINE_C = 7.0;
|
||||
const float SHADER_LINE_D = 8.0;
|
||||
const float SHADER_LINE_E = 9.0;
|
||||
const float SHADER_LINE_F = 10.0;
|
||||
|
||||
// Minimum line width
|
||||
const float MIN_WIDTH = 1.0;
|
||||
|
||||
attribute vec4 attrShaderParams;
|
||||
varying vec4 shaderParams;
|
||||
varying vec2 circleCoords;
|
||||
uniform float worldPixelSize;
|
||||
uniform vec2 screenPixelSize;
|
||||
uniform float pixelSizeMultiplier;
|
||||
uniform float minLinePixelWidth;
|
||||
uniform vec2 antialiasingOffset;
|
||||
|
||||
|
||||
float roundr( float f, float r )
|
||||
{
|
||||
return floor(f / r + 0.5) * r;
|
||||
}
|
||||
|
||||
vec4 roundv( vec4 x, vec2 t)
|
||||
{
|
||||
return vec4( roundr(x.x, t.x), roundr(x.y, t.y), x.z, x.w );
|
||||
}
|
||||
|
||||
void computeLineCoords( bool posture, vec2 vs, vec2 vp, vec2 texcoord, vec2 dir, float lineWidth, bool endV )
|
||||
{
|
||||
float lineLength = length(vs);
|
||||
vec4 screenPos = gl_ModelViewProjectionMatrix * gl_Vertex + vec4(1, 1, 0, 0);
|
||||
float w = ((lineWidth == 0.0) ? worldPixelSize : lineWidth );
|
||||
float pixelWidth = roundr( w / worldPixelSize, 1.0 );
|
||||
float aspect = ( lineLength + w ) / w;
|
||||
vec4 color = gl_Color;
|
||||
vec2 s = sign( vec2( gl_ModelViewProjectionMatrix[0][0], gl_ModelViewProjectionMatrix[1][1] ) );
|
||||
|
||||
|
||||
if( pixelWidth < 1.0 )
|
||||
pixelWidth = 1.0;
|
||||
|
||||
if ( pixelWidth > 1.0 || pixelSizeMultiplier > 1.0 )
|
||||
{
|
||||
vec2 offsetNorm = (vs + vp) * pixelWidth / lineLength * 0.5;
|
||||
vec4 screenOffset = vec4( s.x * offsetNorm.x * screenPixelSize.x, s.y * offsetNorm.y * screenPixelSize.y , 0, 0);
|
||||
vec4 adjust = vec4(-1, -1, 0, 0);
|
||||
|
||||
if( mod( pixelWidth * pixelSizeMultiplier, 2.0 ) > 0.9 )
|
||||
{
|
||||
adjust += vec4( screenPixelSize.x, screenPixelSize.y, 0, 0 ) * 0.5;
|
||||
}
|
||||
|
||||
gl_Position = roundv(screenPos, screenPixelSize) + adjust + screenOffset;
|
||||
|
||||
shaderParams[0] = SHADER_LINE_A;
|
||||
}
|
||||
else {
|
||||
vec4 pos0 = screenPos;
|
||||
pos0.xy += ( posture ? dir.xy : dir.yx ) * screenPixelSize / 2.0;
|
||||
|
||||
if(posture)
|
||||
{
|
||||
pos0.y -= screenPixelSize.y * sign(vs.y) * 0.5;
|
||||
}
|
||||
else
|
||||
{
|
||||
pos0.x += screenPixelSize.x * sign(vs.x) * 0.5;
|
||||
}
|
||||
|
||||
gl_Position = pos0 - vec4(1, 1, 0, 0);
|
||||
shaderParams[0] = SHADER_LINE_B;
|
||||
}
|
||||
|
||||
shaderParams[1] = aspect;
|
||||
|
||||
gl_TexCoord[0].st = vec2(aspect * texcoord.x, texcoord.y);
|
||||
gl_FrontColor = gl_Color;
|
||||
}
|
||||
|
||||
|
||||
void computeCircleCoords( float mode, float vertexIndex, float radius, float lineWidth )
|
||||
{
|
||||
vec4 delta;
|
||||
vec4 center = roundv( gl_ModelViewProjectionMatrix * gl_Vertex + vec4(1, 1, 0, 0), screenPixelSize );
|
||||
float pixelWidth = roundr( lineWidth / worldPixelSize, 1.0);
|
||||
float pixelR = roundr( radius / worldPixelSize, 1.0);
|
||||
|
||||
if( mode == SHADER_STROKED_CIRCLE)
|
||||
pixelR += pixelWidth / 2.0;
|
||||
|
||||
vec4 adjust = vec4(-1, -1, 0, 0);
|
||||
|
||||
if( pixelWidth < 1.0 )
|
||||
pixelWidth = 1.0;
|
||||
|
||||
if( vertexIndex == 1.0 )
|
||||
{
|
||||
circleCoords = vec2( -sqrt( 3.0 ), -1.0 );
|
||||
delta = vec4( -pixelR * sqrt(3.0), -pixelR, 0, 0 );
|
||||
}
|
||||
else if( vertexIndex == 2.0 )
|
||||
{
|
||||
circleCoords = vec2( sqrt( 3.0 ), -1.0 );
|
||||
delta = vec4( pixelR * sqrt( 3.0 ), -pixelR, 0, 0 );
|
||||
}
|
||||
else if( vertexIndex == 3.0 )
|
||||
{
|
||||
circleCoords = vec2( 0.0, 2.0 );
|
||||
delta = vec4( 0, 2 * pixelR, 0, 0 );
|
||||
}
|
||||
else if( vertexIndex == 4.0 )
|
||||
{
|
||||
circleCoords = vec2( -sqrt( 3.0 ), 0.0 );
|
||||
delta = vec4( 0, 0, 0, 0 );
|
||||
}
|
||||
else if( vertexIndex == 5.0 )
|
||||
{
|
||||
circleCoords = vec2( sqrt( 3.0 ), 0.0 );
|
||||
delta = vec4( 0, 0, 0, 0 );
|
||||
}
|
||||
else if( vertexIndex == 6.0 )
|
||||
{
|
||||
circleCoords = vec2( 0.0, 2.0 );
|
||||
delta = vec4( 0, 0, 0, 0 );
|
||||
}
|
||||
|
||||
shaderParams[2] = pixelR;
|
||||
shaderParams[3] = pixelWidth;
|
||||
|
||||
delta.x *= screenPixelSize.x;
|
||||
delta.y *= screenPixelSize.y;
|
||||
|
||||
gl_Position = center + delta + adjust;
|
||||
gl_FrontColor = gl_Color;
|
||||
}
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
float mode = attrShaderParams[0];
|
||||
|
||||
// Pass attributes to the fragment shader
|
||||
shaderParams = attrShaderParams;
|
||||
|
||||
float lineWidth = shaderParams.y;
|
||||
vec2 vs = shaderParams.zw;
|
||||
vec2 vp = vec2(-vs.y, vs.x);
|
||||
bool posture = abs( vs.x ) < abs(vs.y);
|
||||
|
||||
if( mode == SHADER_LINE_A )
|
||||
computeLineCoords( posture, -vs, vp, vec2( -1, -1 ), vec2( -1, 0 ), lineWidth, false );
|
||||
else if( mode == SHADER_LINE_B )
|
||||
computeLineCoords( posture, -vs, -vp, vec2( -1, 1 ), vec2( 1, 0 ), lineWidth, false );
|
||||
else if( mode == SHADER_LINE_C )
|
||||
computeLineCoords( posture, vs, -vp, vec2( 1, 1 ), vec2( 1, 0 ), lineWidth, true );
|
||||
else if( mode == SHADER_LINE_D )
|
||||
computeLineCoords( posture, vs, -vp, vec2( -1, -1 ), vec2( 1, 0 ), lineWidth, true );
|
||||
else if( mode == SHADER_LINE_E )
|
||||
computeLineCoords( posture, vs, vp, vec2( -1, 1 ), vec2( -1, 0 ), lineWidth, true );
|
||||
else if( mode == SHADER_LINE_F )
|
||||
computeLineCoords( posture, -vs, vp, vec2( 1, 1 ), vec2( -1, 0 ), lineWidth, false );
|
||||
else if( mode == SHADER_FILLED_CIRCLE || mode == SHADER_STROKED_CIRCLE)
|
||||
computeCircleCoords( mode, shaderParams.y, shaderParams.z, shaderParams.w );
|
||||
else
|
||||
{
|
||||
// Pass through the coordinates like in the fixed pipeline
|
||||
gl_Position = ftransform();
|
||||
gl_FrontColor = gl_Color;
|
||||
|
||||
}
|
||||
|
||||
gl_Position.xy += antialiasingOffset;
|
||||
}
|
Loading…
Reference in New Issue