Commit 28511cf4 authored by Maciej Suminski's avatar Maciej Suminski

Introducing shaders.

Shader's parameters are stored in VBO_ITEM. Changed VBO_ITEM data structure. Added UseShader() function for selecting shader for a given VBO_ITEM.
Added one main vertex & fragment shader program to be used for with all kinds of items (type of shader is selected using attributes that are stored in VBO). Currently available shaders are: at-least-1px-width line, filled circle and stroked circle.
Removed unnecessary param (aDepthOffset) from a few functions (OPENGL_GAL::drawSemiCircle(), OPENGL_GAL::drawLineCap()). Removed function OPENGL_GAL::DrawRoundedSegment(). Changed some asserts to debug info or error log.
parent ad5d10a8
...@@ -58,9 +58,9 @@ EDA_DRAW_PANEL_GAL::EDA_DRAW_PANEL_GAL( wxWindow* aParentWindow, wxWindowID aWin ...@@ -58,9 +58,9 @@ EDA_DRAW_PANEL_GAL::EDA_DRAW_PANEL_GAL( wxWindow* aParentWindow, wxWindowID aWin
wxStandardPaths paths; wxStandardPaths paths;
wxFileName executableFile( paths.GetExecutablePath() ); wxFileName executableFile( paths.GetExecutablePath() );
m_galShaderPath = std::string( ( executableFile.GetPath() + m_galShaderPath = std::string( ( executableFile.GetPath() +
wxT( "/../../common/gal/opengl/shader/" ) ).mb_str() ); wxT( "/../../common/gal/opengl/" ) ).mb_str() );
SwitchBackend( aGalType, false ); SwitchBackend( aGalType, true );
SetBackgroundStyle( wxBG_STYLE_CUSTOM ); SetBackgroundStyle( wxBG_STYLE_CUSTOM );
// Initial display settings // Initial display settings
......
...@@ -26,8 +26,9 @@ ...@@ -26,8 +26,9 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/ */
#include <cmath>
#include <gal/opengl/opengl_gal.h> #include <gal/opengl/opengl_gal.h>
#include <gal/opengl/shader.h>
#include <gal/definitions.h> #include <gal/definitions.h>
#include <gal/opengl/glm/gtc/matrix_transform.hpp> #include <gal/opengl/glm/gtc/matrix_transform.hpp>
...@@ -71,22 +72,20 @@ OPENGL_GAL::OPENGL_GAL( wxWindow* aParent, wxEvtHandler* aMouseListener, ...@@ -71,22 +72,20 @@ OPENGL_GAL::OPENGL_GAL( wxWindow* aParent, wxEvtHandler* aMouseListener,
isUseShader = isUseShaders; isUseShader = isUseShaders;
isShaderInitialized = false; isShaderInitialized = false;
isGrouping = false; isGrouping = false;
shaderPath = "../../common/gal/opengl/shader/"; shaderPath = "../../common/gal/opengl";
wxSize parentSize = aParent->GetSize(); wxSize parentSize = aParent->GetSize();
isVboInitialized = false; isVboInitialized = false;
vboNeedsUpdate = false; vboNeedsUpdate = false;
curVboItem = NULL; curVboItem = NULL;
vboSize = 0; vboSize = 0;
transform = glm::mat4( 1.0f ); transform = glm::mat4( 1.0f ); // Identity matrix
SetSize( parentSize ); SetSize( parentSize );
screenSize.x = parentSize.x; screenSize.x = parentSize.x;
screenSize.y = parentSize.y; screenSize.y = parentSize.y;
currentShader = -1;
// Set grid defaults // Set grid defaults
SetGridColor( COLOR4D( 0.3, 0.3, 0.3, 0.3 ) ); SetGridColor( COLOR4D( 0.3, 0.3, 0.3, 0.3 ) );
SetCoarseGrid( 10 ); SetCoarseGrid( 10 );
...@@ -108,10 +107,13 @@ OPENGL_GAL::OPENGL_GAL( wxWindow* aParent, wxEvtHandler* aMouseListener, ...@@ -108,10 +107,13 @@ OPENGL_GAL::OPENGL_GAL( wxWindow* aParent, wxEvtHandler* aMouseListener,
Connect( wxEVT_ENTER_WINDOW, wxMouseEventHandler( OPENGL_GAL::skipMouseEvent ) ); Connect( wxEVT_ENTER_WINDOW, wxMouseEventHandler( OPENGL_GAL::skipMouseEvent ) );
#endif #endif
// Compute the unit circles, used for speed up of the circle drawing if( !isUseShader )
computeUnitCircle(); {
computeUnitSemiCircle(); // Compute the unit circles, used for speed up of the circle drawing
// computeUnitArcs(); // TODO it is not used anywhere computeUnitCircle();
computeUnitSemiCircle();
//computeUnitArcs(); // TODO remove? it is not used anywhere
}
} }
...@@ -346,18 +348,18 @@ void OPENGL_GAL::BeginDrawing() ...@@ -346,18 +348,18 @@ void OPENGL_GAL::BeginDrawing()
// Compile the shaders // Compile the shaders
if( !isShaderInitialized && isUseShader ) if( !isShaderInitialized && isUseShader )
{ {
std::string shaderNames[SHADER_NUMBER] = { std::string( "round" ) }; shader.ConfigureGeometryShader( 3, GL_TRIANGLES, GL_TRIANGLES );
shader.AddSource( shaderPath + std::string( "/shader.vert" ), SHADER_TYPE_VERTEX );
for( int i = 0; i < 1; i++ ) shader.AddSource( shaderPath + std::string( "/shader.frag" ), SHADER_TYPE_FRAGMENT );
if( !shader.Link() )
{ {
shaderList.push_back( SHADER() ); wxLogFatalError( wxT( "Cannot link the shaders!" ) );
}
shaderList[i].AddSource( shaderPath + std::string( "/" ) + shaderNames[i] +
std::string( ".frag" ), SHADER_TYPE_FRAGMENT );
shaderList[i].AddSource( shaderPath + std::string( "/" ) + shaderNames[i] +
std::string( ".vert" ), SHADER_TYPE_VERTEX );
shaderList[i].Link(); shaderAttrib = shader.GetAttribute( "attrShaderParams" );
if( shaderAttrib == -1 )
{
wxLogFatalError( wxT( "Could not get the shader attribute location" ) );
} }
isShaderInitialized = true; isShaderInitialized = true;
...@@ -420,7 +422,8 @@ void OPENGL_GAL::BeginDrawing() ...@@ -420,7 +422,8 @@ void OPENGL_GAL::BeginDrawing()
void OPENGL_GAL::blitMainTexture( bool aIsClearFrameBuffer ) void OPENGL_GAL::blitMainTexture( bool aIsClearFrameBuffer )
{ {
selectShader( -1 ); shader.Deactivate();
// Don't use blending for the final blitting // Don't use blending for the final blitting
glDisable( GL_BLEND ); glDisable( GL_BLEND );
...@@ -474,25 +477,41 @@ void OPENGL_GAL::EndDrawing() ...@@ -474,25 +477,41 @@ void OPENGL_GAL::EndDrawing()
glEnableClientState( GL_VERTEX_ARRAY ); glEnableClientState( GL_VERTEX_ARRAY );
glEnableClientState( GL_COLOR_ARRAY ); glEnableClientState( GL_COLOR_ARRAY );
// Bind vertices data buffer and point to the data // Bind vertices data buffers
glBindBuffer( GL_ARRAY_BUFFER, curVboVertId ); glBindBuffer( GL_ARRAY_BUFFER, curVboVertId );
glVertexPointer( 3, GL_FLOAT, VBO_ITEM::VertSize, 0 ); glVertexPointer( VBO_ITEM::CoordStride, GL_FLOAT, VBO_ITEM::VertByteSize, 0 );
glColorPointer( 4, GL_FLOAT, VBO_ITEM::VertSize, (GLvoid*) VBO_ITEM::ColorByteOffset ); glColorPointer( VBO_ITEM::ColorStride, GL_FLOAT, VBO_ITEM::VertByteSize,
(GLvoid*) VBO_ITEM::ColorByteOffset );
// Shader parameters
if( isUseShader )
{
shader.Use();
glEnableVertexAttribArray( shaderAttrib );
glVertexAttribPointer( shaderAttrib, VBO_ITEM::ShaderStride, GL_FLOAT, GL_FALSE,
VBO_ITEM::VertByteSize, (GLvoid*) VBO_ITEM::ShaderByteOffset );
}
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, curVboIndId ); glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, curVboIndId );
GLuint* indicesPtr = static_cast<GLuint*>( glMapBuffer( GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY ) ); GLuint* indicesPtr = static_cast<GLuint*>( glMapBuffer( GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY ) );
wxASSERT_MSG( indicesPtr != NULL, "OPENGL_GAL::EndDrawing: Could not map GPU memory" ); if( indicesPtr == NULL )
{
wxLogError( wxT( "Could not map GPU memory" ) );
}
// Copy indices of items that should be drawn to GPU memory
std::list<VBO_ITEM*>::const_iterator it, end; std::list<VBO_ITEM*>::const_iterator it, end;
for( it = itemsToDraw.begin(), end = itemsToDraw.end(); it != end; ++it ) for( it = itemsToDraw.begin(), end = itemsToDraw.end(); it != end; ++it )
{ {
memcpy( indicesPtr, (*it)->GetIndices(), (*it)->GetSize() * VBO_ITEM::IndSize ); memcpy( indicesPtr, (*it)->GetIndices(), (*it)->GetSize() * VBO_ITEM::IndByteSize );
indicesPtr += (*it)->GetSize() * VBO_ITEM::IndStride; indicesPtr += (*it)->GetSize() * VBO_ITEM::IndStride;
} }
bool result = glUnmapBuffer( GL_ELEMENT_ARRAY_BUFFER ); if( !glUnmapBuffer( GL_ELEMENT_ARRAY_BUFFER ) )
wxASSERT_MSG( result == TRUE, "OPENGL_GAL::EndDrawing: Unmapping indices buffer failed" ); {
wxLogError( wxT( "Unmapping indices buffer failed" ) );
}
glDrawElements( GL_TRIANGLES, itemsToDrawSize, GL_UNSIGNED_INT, (GLvoid*) 0 ); glDrawElements( GL_TRIANGLES, itemsToDrawSize, GL_UNSIGNED_INT, (GLvoid*) 0 );
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 ); glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 );
...@@ -501,6 +520,11 @@ void OPENGL_GAL::EndDrawing() ...@@ -501,6 +520,11 @@ void OPENGL_GAL::EndDrawing()
// Deactivate vertex array // Deactivate vertex array
glDisableClientState( GL_COLOR_ARRAY ); glDisableClientState( GL_COLOR_ARRAY );
glDisableClientState( GL_VERTEX_ARRAY ); glDisableClientState( GL_VERTEX_ARRAY );
if( isUseShader )
{
glDisableVertexAttribArray( shaderAttrib );
shader.Deactivate();
}
// Draw the remaining contents, blit the main texture to the screen, swap the buffers // Draw the remaining contents, blit the main texture to the screen, swap the buffers
glFlush(); glFlush();
...@@ -538,18 +562,18 @@ void OPENGL_GAL::rebuildVbo() ...@@ -538,18 +562,18 @@ void OPENGL_GAL::rebuildVbo()
{ {
int size = (*vboItem)->GetSize(); int size = (*vboItem)->GetSize();
memcpy( verticesBufferPtr, (*vboItem)->GetVertices(), size * VBO_ITEM::VertSize ); memcpy( verticesBufferPtr, (*vboItem)->GetVertices(), size * VBO_ITEM::VertByteSize );
verticesBufferPtr += size * VBO_ITEM::VertStride; verticesBufferPtr += size * VBO_ITEM::VertStride;
} }
// Upload vertices coordinates and indices to GPU memory // Upload vertices coordinates, shader types and indices to GPU memory
glBindBuffer( GL_ARRAY_BUFFER, curVboVertId ); glBindBuffer( GL_ARRAY_BUFFER, curVboVertId );
glBufferData( GL_ARRAY_BUFFER, vboSize * VBO_ITEM::VertSize, verticesBuffer, GL_DYNAMIC_DRAW ); glBufferData( GL_ARRAY_BUFFER, vboSize * VBO_ITEM::VertByteSize, verticesBuffer, GL_DYNAMIC_DRAW );
glBindBuffer( GL_ARRAY_BUFFER, 0 ); glBindBuffer( GL_ARRAY_BUFFER, 0 );
// Allocate the biggest possible buffer for indices // Allocate the biggest possible buffer for indices
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, curVboIndId ); glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, curVboIndId );
glBufferData( GL_ELEMENT_ARRAY_BUFFER, vboSize * VBO_ITEM::IndSize, NULL, GL_STREAM_DRAW ); glBufferData( GL_ELEMENT_ARRAY_BUFFER, vboSize * VBO_ITEM::IndByteSize, NULL, GL_STREAM_DRAW );
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 ); glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 );
delete[] verticesBuffer; delete[] verticesBuffer;
...@@ -558,112 +582,90 @@ void OPENGL_GAL::rebuildVbo() ...@@ -558,112 +582,90 @@ void OPENGL_GAL::rebuildVbo()
#ifdef __WXDEBUG__ #ifdef __WXDEBUG__
prof_end( &totalTime ); prof_end( &totalTime );
wxLogDebug( wxT( "Rebuilding VBO::items %d / %.1f ms" ), wxLogDebug( wxT( "Rebuilding VBO::%d vertices / %.1f ms" ),
vboSize, (double) totalTime.value / 1000.0 ); vboSize, (double) totalTime.value / 1000.0 );
#endif /* __WXDEBUG__ */ #endif /* __WXDEBUG__ */
} }
inline void OPENGL_GAL::selectShader( int aIndex ) inline void OPENGL_GAL::drawLineQuad( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint )
{ {
if( currentShader != aIndex ) VECTOR2D startEndVector = aEndPoint - aStartPoint;
{ double lineLength = startEndVector.EuclideanNorm();
if( currentShader >= 0 ) double scale = 0.5 * lineWidth / lineLength;
shaderList[currentShader].Deactivate();
if( aIndex >= 0 )
shaderList[aIndex].Use();
currentShader = aIndex; #ifdef __WXDEBUG__
if( lineLength > 0.0 )
{
wxLogDebug( wxT( "Tried to draw line with length <= 0" ) );
} }
} #endif /* __WXDEBUG__ */
void OPENGL_GAL::drawRoundedSegment( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint, if( lineLength <= 0.0 )
double aWidth, bool aStroke, bool aGlBegin ) return;
{
VECTOR2D l = ( aEndPoint - aStartPoint );
double lnorm = l.EuclideanNorm();
double aspect;
if( l.x == 0 && l.y == 0 ) if( lineWidth * worldScale < 1.0002 && !isGrouping && !isUseShader )
{
l = VECTOR2D( aWidth / 2.0, 0.0 );
aspect = 0.0;
}
else
{ {
l = l.Resize( aWidth / 2.0 ); // Limit the width of the line to a minimum of one pixel
aspect = lnorm / (lnorm + aWidth); // this looks best without anti-aliasing
scale = 0.5001 / worldScale / lineLength;
} }
VECTOR2D p = l.Perpendicular(); VECTOR2D perpendicularVector( -startEndVector.y * scale, startEndVector.x * scale );
VECTOR2D corners[4] = { aStartPoint - l - p, aEndPoint + l - p,
aEndPoint + l + p, aStartPoint - l + p };
if( aStroke ) begin( GL_TRIANGLES );
{
color4( strokeColor.r, strokeColor.g, strokeColor.b, strokeColor.a ); if( isUseShader )
}
else
{ {
color4( fillColor.r, fillColor.g, fillColor.b, fillColor.a ); glm::vec4 vector( perpendicularVector.x, perpendicularVector.y, 0.0, 0.0 );
}
selectShader( 0 ); // If transform stack is not empty, then it means that
// there is a transformation matrix that has to be applied
if( !transformStack.empty() )
{
vector = transform * vector;
}
else
{
glm::vec4 vector( perpendicularVector.x, perpendicularVector.y, 0.0, 0.0 );
}
if( aGlBegin ) // Line width is maintained by the vertex shader
glBegin( GL_QUADS ); // shader setShader( SHADER_LINE, vector.x, vector.y, lineWidth );
vertex3( aStartPoint.x, aStartPoint.y, layerDepth ); // v0
glNormal3d( aspect, 0, 0 ); setShader( SHADER_LINE, -vector.x, -vector.y, lineWidth );
glTexCoord2f( 0.0, 0.0 ); vertex3( aStartPoint.x, aStartPoint.y, layerDepth ); // v1
glVertex3d( corners[0].x, corners[0].y, layerDepth );
glNormal3d( aspect, 0, 0 );
glTexCoord2f( 1.0, 0.0 );
glVertex3d( corners[1].x, corners[1].y, layerDepth );
glNormal3d( aspect, 0, 0 );
glTexCoord2f( 1.0, 1.0 );
glVertex3d( corners[2].x, corners[2].y, layerDepth );
glNormal3d( aspect, 0, 0 );
glTexCoord2f( 0.0, 1.0 );
glVertex3d( corners[3].x, corners[3].y, layerDepth );
if( aGlBegin ) setShader( SHADER_LINE, -vector.x, -vector.y, lineWidth );
glEnd(); vertex3( aEndPoint.x, aEndPoint.y, layerDepth ); // v3
}
setShader( SHADER_LINE, vector.x, vector.y, lineWidth );
vertex3( aStartPoint.x, aStartPoint.y, layerDepth ); // v0
inline void OPENGL_GAL::drawLineQuad( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint ) setShader( SHADER_LINE, -vector.x, -vector.y, lineWidth );
{ vertex3( aEndPoint.x, aEndPoint.y, layerDepth ); // v3
VECTOR2D startEndVector = aEndPoint - aStartPoint;
double lineLength = startEndVector.EuclideanNorm();
// Limit the width of the line to a minimum of one pixel setShader( SHADER_LINE, vector.x, vector.y, lineWidth );
// this looks best without anti-aliasing vertex3( aEndPoint.x, aEndPoint.y, layerDepth ); // v2
// XXX Should be improved later.
double scale = 0.5 * lineWidth / lineLength;
double scale1pix = 0.5001 / worldScale / lineLength;
if( lineWidth * worldScale < 1.0002 && !isGrouping )
{
scale = scale1pix;
} }
else
{
// Compute the edge points of the line
VECTOR2D v0 = aStartPoint + perpendicularVector;
VECTOR2D v1 = aStartPoint - perpendicularVector;
VECTOR2D v2 = aEndPoint + perpendicularVector;
VECTOR2D v3 = aEndPoint - perpendicularVector;
VECTOR2D perpendicularVector( -startEndVector.y * scale, startEndVector.x * scale ); vertex3( v0.x, v0.y, layerDepth );
vertex3( v1.x, v1.y, layerDepth );
// Compute the edge points of the line vertex3( v3.x, v3.y, layerDepth );
VECTOR2D v0 = aStartPoint + perpendicularVector;
VECTOR2D v1 = aStartPoint - perpendicularVector;
VECTOR2D v2 = aEndPoint + perpendicularVector;
VECTOR2D v3 = aEndPoint - perpendicularVector;
begin( GL_TRIANGLES ); vertex3( v0.x, v0.y, layerDepth );
vertex3( v0.x, v0.y, layerDepth ); vertex3( v3.x, v3.y, layerDepth );
vertex3( v1.x, v1.y, layerDepth ); vertex3( v2.x, v2.y, layerDepth );
vertex3( v3.x, v3.y, layerDepth ); }
vertex3( v0.x, v0.y, layerDepth );
vertex3( v3.x, v3.y, layerDepth );
vertex3( v2.x, v2.y, layerDepth );
end(); end();
} }
...@@ -676,15 +678,17 @@ void OPENGL_GAL::DrawSegment( const VECTOR2D& aStartPoint, const VECTOR2D& aEndP ...@@ -676,15 +678,17 @@ void OPENGL_GAL::DrawSegment( const VECTOR2D& aStartPoint, const VECTOR2D& aEndP
if( isFillEnabled ) if( isFillEnabled )
{ {
// Filled tracks
color4( fillColor.r, fillColor.g, fillColor.b, fillColor.a ); color4( fillColor.r, fillColor.g, fillColor.b, fillColor.a );
SetLineWidth( aWidth ); SetLineWidth( aWidth );
drawSemiCircle( aStartPoint, aWidth / 2, lineAngle + M_PI / 2, layerDepth ); drawSemiCircle( aStartPoint, aWidth / 2, lineAngle + M_PI / 2 );
drawSemiCircle( aEndPoint, aWidth / 2, lineAngle - M_PI / 2, layerDepth ); drawSemiCircle( aEndPoint, aWidth / 2, lineAngle - M_PI / 2 );
drawLineQuad( aStartPoint, aEndPoint ); drawLineQuad( aStartPoint, aEndPoint );
} }
else else
{ {
// Outlined tracks
double lineLength = startEndVector.EuclideanNorm(); double lineLength = startEndVector.EuclideanNorm();
color4( strokeColor.r, strokeColor.g, strokeColor.b, strokeColor.a ); color4( strokeColor.r, strokeColor.g, strokeColor.b, strokeColor.a );
...@@ -700,16 +704,15 @@ void OPENGL_GAL::DrawSegment( const VECTOR2D& aStartPoint, const VECTOR2D& aEndP ...@@ -700,16 +704,15 @@ void OPENGL_GAL::DrawSegment( const VECTOR2D& aStartPoint, const VECTOR2D& aEndP
drawLineQuad( VECTOR2D( 0.0, -aWidth / 2.0 ), drawLineQuad( VECTOR2D( 0.0, -aWidth / 2.0 ),
VECTOR2D( lineLength, -aWidth / 2.0 ) ); VECTOR2D( lineLength, -aWidth / 2.0 ) );
DrawArc( VECTOR2D( 0.0, 0.0 ), aWidth / 2.0, M_PI / 2.0, 3.0 * M_PI / 2.0 ); drawSemiCircle( VECTOR2D( 0.0, 0.0 ), aWidth / 2, M_PI / 2 );
DrawArc( VECTOR2D( lineLength, 0.0 ), aWidth / 2.0, M_PI / 2.0, -M_PI / 2.0 ); drawSemiCircle( VECTOR2D( lineLength, 0.0 ), aWidth / 2, -M_PI / 2 );
Restore(); Restore();
} }
} }
inline void OPENGL_GAL::drawLineCap( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint, inline void OPENGL_GAL::drawLineCap( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint )
double aDepthOffset )
{ {
VECTOR2D startEndVector = aEndPoint - aStartPoint; VECTOR2D startEndVector = aEndPoint - aStartPoint;
// double lineLength = startEndVector.EuclideanNorm(); // double lineLength = startEndVector.EuclideanNorm();
...@@ -723,7 +726,7 @@ inline void OPENGL_GAL::drawLineCap( const VECTOR2D& aStartPoint, const VECTOR2D ...@@ -723,7 +726,7 @@ inline void OPENGL_GAL::drawLineCap( const VECTOR2D& aStartPoint, const VECTOR2D
case LINE_CAP_ROUND: case LINE_CAP_ROUND:
// Add a semicircle at the line end // Add a semicircle at the line end
drawSemiCircle( aStartPoint, lineWidth / 2, lineAngle + M_PI / 2, aDepthOffset ); drawSemiCircle( aStartPoint, lineWidth / 2, lineAngle + M_PI / 2 );
break; break;
case LINE_CAP_SQUARED: case LINE_CAP_SQUARED:
...@@ -754,6 +757,7 @@ void OPENGL_GAL::vertex3( double aX, double aY, double aZ ) ...@@ -754,6 +757,7 @@ void OPENGL_GAL::vertex3( double aX, double aY, double aZ )
{ {
if( isGrouping ) if( isGrouping )
{ {
// New vertex coordinates for VBO
const GLfloat vertex[] = { aX, aY, aZ }; const GLfloat vertex[] = { aX, aY, aZ };
curVboItem->PushVertex( vertex ); curVboItem->PushVertex( vertex );
} }
...@@ -805,31 +809,46 @@ void OPENGL_GAL::color4( const COLOR4D& aColor ) ...@@ -805,31 +809,46 @@ void OPENGL_GAL::color4( const COLOR4D& aColor )
void OPENGL_GAL::DrawLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint ) void OPENGL_GAL::DrawLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint )
{ {
if( isUseShader ) if( isFillEnabled )
{ {
drawRoundedSegment( aStartPoint, aEndPoint, lineWidth, true, true ); color4( fillColor.r, fillColor.g, fillColor.b, fillColor.a );
drawLineCap( aStartPoint, aEndPoint );
drawLineCap( aEndPoint, aStartPoint );
drawLineQuad( aStartPoint, aEndPoint );
} }
else
if( isStrokeEnabled )
{ {
VECTOR2D startEndVector = aEndPoint - aStartPoint; // TODO outline mode
double lineLength = startEndVector.EuclideanNorm(); color4( strokeColor.r, strokeColor.g, strokeColor.b, strokeColor.a );
if( lineLength > 0.0 )
{
color4( strokeColor.r, strokeColor.g, strokeColor.b, strokeColor.a );
drawLineCap( aStartPoint, aEndPoint, layerDepth ); drawLineCap( aStartPoint, aEndPoint );
drawLineCap( aEndPoint, aStartPoint, layerDepth ); drawLineCap( aEndPoint, aStartPoint );
drawLineQuad( aStartPoint, aEndPoint ); drawLineQuad( aStartPoint, aEndPoint );
}
} }
} }
void OPENGL_GAL::DrawPolyline( std::deque<VECTOR2D>& aPointList ) void OPENGL_GAL::DrawPolyline( std::deque<VECTOR2D>& aPointList )
{ {
LineCap savedLineCap = lineCap;
bool isFirstPoint = true; bool isFirstPoint = true;
if( isUseShader )
{
// This method reduces amount of triangles used for drawing
std::deque<VECTOR2D>::const_iterator it = aPointList.begin();
// Start from the second point
for( it++; it != aPointList.end(); it++ )
{
DrawLine( *( it - 1 ), *it );
}
return;
}
LineCap savedLineCap = lineCap;
bool isFirstLine = true; bool isFirstLine = true;
VECTOR2D startEndVector; VECTOR2D startEndVector;
VECTOR2D lastStartEndVector; VECTOR2D lastStartEndVector;
...@@ -854,7 +873,7 @@ void OPENGL_GAL::DrawPolyline( std::deque<VECTOR2D>& aPointList ) ...@@ -854,7 +873,7 @@ void OPENGL_GAL::DrawPolyline( std::deque<VECTOR2D>& aPointList )
if( isFirstLine ) if( isFirstLine )
{ {
drawLineCap( lastPoint, actualPoint, layerDepth ); drawLineCap( lastPoint, actualPoint );
isFirstLine = false; isFirstLine = false;
} }
else else
...@@ -1029,7 +1048,7 @@ void OPENGL_GAL::DrawPolyline( std::deque<VECTOR2D>& aPointList ) ...@@ -1029,7 +1048,7 @@ void OPENGL_GAL::DrawPolyline( std::deque<VECTOR2D>& aPointList )
if( it == aPointList.end() - 1 ) if( it == aPointList.end() - 1 )
{ {
drawLineCap( actualPoint, lastPoint, layerDepth ); drawLineCap( actualPoint, lastPoint );
} }
drawLineQuad( lastPoint, *it ); drawLineQuad( lastPoint, *it );
...@@ -1050,47 +1069,11 @@ void OPENGL_GAL::DrawRectangle( const VECTOR2D& aStartPoint, const VECTOR2D& aEn ...@@ -1050,47 +1069,11 @@ void OPENGL_GAL::DrawRectangle( const VECTOR2D& aStartPoint, const VECTOR2D& aEn
VECTOR2D diagonalPointA( aEndPoint.x, aStartPoint.y ); VECTOR2D diagonalPointA( aEndPoint.x, aStartPoint.y );
VECTOR2D diagonalPointB( aStartPoint.x, aEndPoint.y ); VECTOR2D diagonalPointB( aStartPoint.x, aEndPoint.y );
if( isUseShader )
{
if( isFillEnabled )
{
selectShader( 0 );
glColor4d( fillColor.r, fillColor.g, fillColor.b, fillColor.a );
glBegin( GL_QUADS ); // shader
glNormal3d( 1.0, 0, 0 );
glTexCoord2f( 0.0, 0.0 );
glVertex3d( aStartPoint.x, aStartPoint.y, layerDepth );
glNormal3d( 1.0, 0, 0 );
glTexCoord2f( 1.0, 0.0 );
glVertex3d( diagonalPointA.x, diagonalPointA.y, layerDepth );
glNormal3d( 1.0, 0, 0 );
glTexCoord2f( 1.0, 1.0 );
glVertex3d( aEndPoint.x, aEndPoint.y, layerDepth );
glNormal3d( 1.0, 0, 0 );
glTexCoord2f( 0.0, 1.0 );
glVertex3d( diagonalPointB.x, diagonalPointB.y, layerDepth );
glEnd();
}
if( isStrokeEnabled )
{
glBegin( GL_QUADS ); // shader
drawRoundedSegment( aStartPoint, diagonalPointA, lineWidth, true, false );
drawRoundedSegment( aEndPoint, diagonalPointA, lineWidth, true, false );
drawRoundedSegment( aStartPoint, diagonalPointB, lineWidth, true, false );
drawRoundedSegment( aEndPoint, diagonalPointB, lineWidth, true, false );
glEnd();
}
return;
}
selectShader( -1 );
// Stroke the outline // Stroke the outline
if( isStrokeEnabled ) if( isStrokeEnabled )
{ {
color4( strokeColor.r, strokeColor.g, strokeColor.b, strokeColor.a ); color4( strokeColor.r, strokeColor.g, strokeColor.b, strokeColor.a );
std::deque<VECTOR2D> pointList; std::deque<VECTOR2D> pointList;
pointList.push_back( aStartPoint ); pointList.push_back( aStartPoint );
pointList.push_back( diagonalPointA ); pointList.push_back( diagonalPointA );
...@@ -1103,6 +1086,7 @@ void OPENGL_GAL::DrawRectangle( const VECTOR2D& aStartPoint, const VECTOR2D& aEn ...@@ -1103,6 +1086,7 @@ void OPENGL_GAL::DrawRectangle( const VECTOR2D& aStartPoint, const VECTOR2D& aEn
// Fill the rectangle // Fill the rectangle
if( isFillEnabled ) if( isFillEnabled )
{ {
setShader( SHADER_NONE );
color4( fillColor.r, fillColor.g, fillColor.b, fillColor.a ); color4( fillColor.r, fillColor.g, fillColor.b, fillColor.a );
begin( GL_TRIANGLES ); begin( GL_TRIANGLES );
...@@ -1115,23 +1099,74 @@ void OPENGL_GAL::DrawRectangle( const VECTOR2D& aStartPoint, const VECTOR2D& aEn ...@@ -1115,23 +1099,74 @@ void OPENGL_GAL::DrawRectangle( const VECTOR2D& aStartPoint, const VECTOR2D& aEn
vertex3( diagonalPointB.x, diagonalPointB.y, layerDepth ); vertex3( diagonalPointB.x, diagonalPointB.y, layerDepth );
end(); end();
} }
// Restore the stroke color
color4( strokeColor.r, strokeColor.g, strokeColor.b, strokeColor.a );
} }
void OPENGL_GAL::DrawCircle( const VECTOR2D& aCenterPoint, double aRadius ) void OPENGL_GAL::DrawCircle( const VECTOR2D& aCenterPoint, double aRadius )
{ {
// We need a minimum radius, else simply don't draw the circle #ifdef __WXDEBUG__
if( aRadius <= 0.0 ) if( aRadius > 0.0 )
{ {
return; wxLogDebug( wxT( "Tried to draw circle with radius <= 0" ) );
} }
#endif /* __WXDEBUG__ */
if( isUseShader ) if( isUseShader )
{ {
drawRoundedSegment( aCenterPoint, aCenterPoint, aRadius * 2.0, false, true ); if( isFillEnabled )
{
color4( fillColor.r, fillColor.g, fillColor.b, fillColor.a );
/* 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.
Shader uses this coordinates to determine if fragments are inside the circle or not.
v2
/\
//\\
v0 /_\/_\ v1
*/
setShader( SHADER_FILLED_CIRCLE, -sqrt( 3.0f ), -1.0f );
vertex3( aCenterPoint.x - aRadius * sqrt( 3.0f ), // v0
aCenterPoint.y - aRadius, layerDepth );
setShader( SHADER_FILLED_CIRCLE, sqrt( 3.0f ), -1.0f );
vertex3( aCenterPoint.x + aRadius * sqrt( 3.0f ), // v1
aCenterPoint.y - aRadius, layerDepth );
setShader( SHADER_FILLED_CIRCLE, 0.0f, 2.0f );
vertex3( aCenterPoint.x, aCenterPoint.y + aRadius * 2.0f, layerDepth ); // v2
}
if( isStrokeEnabled )
{
color4( strokeColor.r, strokeColor.g, strokeColor.b, strokeColor.a );
/* 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
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 relative value.
v2
/\
//\\
v0 /_\/_\ v1
*/
float outerRadius = aRadius + ( lineWidth / 2.0f );
float innerRadius = aRadius - ( lineWidth / 2.0f );
float relWidth = innerRadius / outerRadius;
setShader( SHADER_STROKED_CIRCLE, -sqrt( 3.0f ), -1.0f, relWidth );
vertex3( aCenterPoint.x - outerRadius * sqrt( 3.0f ), // v0
aCenterPoint.y - outerRadius, layerDepth );
setShader( SHADER_STROKED_CIRCLE, sqrt( 3.0f ), -1.0f, relWidth );
vertex3( aCenterPoint.x + outerRadius * sqrt( 3.0f ), // v1
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;
} }
...@@ -1142,12 +1177,6 @@ void OPENGL_GAL::DrawCircle( const VECTOR2D& aCenterPoint, double aRadius ) ...@@ -1142,12 +1177,6 @@ void OPENGL_GAL::DrawCircle( const VECTOR2D& aCenterPoint, double aRadius )
outerScale += 1.0; outerScale += 1.0;
innerScale += 1.0; innerScale += 1.0;
if( isUseShader )
{
// TODO is it ever reached?
innerScale *= 1.0 / cos( M_PI / CIRCLE_POINTS );
}
if( isStrokeEnabled ) if( isStrokeEnabled )
{ {
if( innerScale < outerScale ) if( innerScale < outerScale )
...@@ -1209,24 +1238,53 @@ void OPENGL_GAL::DrawCircle( const VECTOR2D& aCenterPoint, double aRadius ) ...@@ -1209,24 +1238,53 @@ void OPENGL_GAL::DrawCircle( const VECTOR2D& aCenterPoint, double aRadius )
} }
void OPENGL_GAL::drawSemiCircle( const VECTOR2D& aCenterPoint, double aRadius, double aAngle, void OPENGL_GAL::drawSemiCircle( const VECTOR2D& aCenterPoint, double aRadius, double aAngle )
double aDepthOffset )
{ {
Save(); if( isUseShader )
translate3( aCenterPoint.x, aCenterPoint.y, aDepthOffset );
Scale( VECTOR2D( aRadius, aRadius ) );
Rotate( aAngle );
if( isGrouping )
{ {
curVboItem->PushVertices( verticesSemiCircle.GetVertices(), verticesSemiCircle.GetSize() ); Save();
Translate( aCenterPoint );
Rotate( aAngle );
color4( strokeColor.r, strokeColor.g, strokeColor.b, strokeColor.a );
/* 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.
Shader uses this coordinates to determine if fragments are inside the semicircle or not.
v2
/\
/__\
v0 //__\\ v1
*/
setShader( SHADER_FILLED_CIRCLE, -3.0f / sqrt( 3.0f ), 0.0f, lineWidth );
vertex3( -aRadius * 3.0f / sqrt( 3.0f ), 0.0f, layerDepth ); // v0
setShader( SHADER_FILLED_CIRCLE, 3.0f / sqrt( 3.0f ), 0.0f, lineWidth );
vertex3( aRadius * 3.0f / sqrt( 3.0f ), 0.0f, layerDepth ); // v1
setShader( SHADER_FILLED_CIRCLE, 0.0f, 2.0f, lineWidth );
vertex3( 0.0f, aRadius * 2.0f, layerDepth ); // v2
Restore();
} }
else else
{ {
glCallList( displayListSemiCircle ); Save();
} translate3( aCenterPoint.x, aCenterPoint.y, layerDepth );
Scale( VECTOR2D( aRadius, aRadius ) );
Rotate( aAngle );
Restore(); if( isGrouping )
{
curVboItem->PushVertices( verticesSemiCircle.GetVertices(), verticesSemiCircle.GetSize() );
}
else
{
glCallList( displayListSemiCircle );
}
Restore();
}
} }
...@@ -1239,12 +1297,6 @@ void OPENGL_GAL::DrawArc( const VECTOR2D& aCenterPoint, double aRadius, double a ...@@ -1239,12 +1297,6 @@ void OPENGL_GAL::DrawArc( const VECTOR2D& aCenterPoint, double aRadius, double a
return; return;
} }
double outerScale = lineWidth / aRadius / 2;
double innerScale = -outerScale;
outerScale += 1.0;
innerScale += 1.0;
// Swap the angles, if start angle is greater than end angle // Swap the angles, if start angle is greater than end angle
SWAP( aStartAngle, >, aEndAngle ); SWAP( aStartAngle, >, aEndAngle );
...@@ -1254,46 +1306,37 @@ void OPENGL_GAL::DrawArc( const VECTOR2D& aCenterPoint, double aRadius, double a ...@@ -1254,46 +1306,37 @@ void OPENGL_GAL::DrawArc( const VECTOR2D& aCenterPoint, double aRadius, double a
VECTOR2D middlePoint = 0.5 * startEndPoint; VECTOR2D middlePoint = 0.5 * startEndPoint;
Save(); Save();
translate3( aCenterPoint.x, aCenterPoint.y, layerDepth ); translate3( aCenterPoint.x, aCenterPoint.y, 0.0 );
Scale( VECTOR2D( aRadius, aRadius ) );
if( isStrokeEnabled ) if( isStrokeEnabled )
{ {
if( isUseShader ) if( isUseShader )
{ {
int n_points_s = (int) ( aRadius * worldScale ); double alphaIncrement = 2.0 * M_PI / CIRCLE_POINTS;
int n_points_a = (int) ( ( aEndAngle - aStartAngle ) / color4( strokeColor.r, strokeColor.g, strokeColor.b, strokeColor.a );
(double) ( 2.0 * M_PI / CIRCLE_POINTS ) );
if( n_points_s < 4 )
n_points_s = 4;
int n_points = std::min( n_points_s, n_points_a );
if( n_points > CIRCLE_POINTS )
n_points = CIRCLE_POINTS;
double alphaIncrement = ( aEndAngle - aStartAngle ) / n_points;
double cosI = cos( alphaIncrement );
double sinI = sin( alphaIncrement );
VECTOR2D p( cos( aStartAngle ), sin( aStartAngle ) );
glBegin( GL_QUADS ); // shader
for( int i = 0; i < n_points; i++ ) VECTOR2D p( cos( aStartAngle ) * aRadius, sin( aStartAngle ) * aRadius );
for( double alpha = aStartAngle; alpha < aEndAngle; alpha += alphaIncrement )
{ {
VECTOR2D p_next( p.x * cosI - p.y * sinI, p.x * sinI + p.y * cosI ); if( alpha > aEndAngle )
alpha = aEndAngle;
VECTOR2D p_next( cos( alpha ) * aRadius, sin( alpha ) * aRadius );
DrawLine( p, p_next );
drawRoundedSegment( p, p_next, lineWidth / aRadius, true, false );
p = p_next; p = p_next;
} }
glEnd();
} }
else else
{ {
Scale( VECTOR2D( aRadius, aRadius ) );
double outerScale = lineWidth / aRadius / 2;
double innerScale = -outerScale;
outerScale += 1.0;
innerScale += 1.0;
double alphaIncrement = 2 * M_PI / CIRCLE_POINTS; double alphaIncrement = 2 * M_PI / CIRCLE_POINTS;
color4( strokeColor.r, strokeColor.g, strokeColor.b, strokeColor.a ); color4( strokeColor.r, strokeColor.g, strokeColor.b, strokeColor.a );
...@@ -1312,21 +1355,21 @@ void OPENGL_GAL::DrawArc( const VECTOR2D& aCenterPoint, double aRadius, double a ...@@ -1312,21 +1355,21 @@ void OPENGL_GAL::DrawArc( const VECTOR2D& aCenterPoint, double aRadius, double a
double v2[] = { cos( alpha ) * innerScale, sin( alpha ) * innerScale }; double v2[] = { cos( alpha ) * innerScale, sin( alpha ) * innerScale };
double v3[] = { cos( alpha ) * outerScale, sin( alpha ) * outerScale }; double v3[] = { cos( alpha ) * outerScale, sin( alpha ) * outerScale };
vertex3( v0[0], v0[1], 0.0 ); vertex3( v0[0], v0[1], layerDepth );
vertex3( v1[0], v1[1], 0.0 ); vertex3( v1[0], v1[1], layerDepth );
vertex3( v2[0], v2[1], 0.0 ); vertex3( v2[0], v2[1], layerDepth );
vertex3( v1[0], v1[1], 0.0 ); vertex3( v1[0], v1[1], layerDepth );
vertex3( v3[0], v3[1], 0.0 ); vertex3( v3[0], v3[1], layerDepth );
vertex3( v2[0], v2[1], 0.0 ); vertex3( v2[0], v2[1], layerDepth );
} }
end(); end();
if( lineCap == LINE_CAP_ROUND ) if( lineCap == LINE_CAP_ROUND )
{ {
drawSemiCircle( startPoint, lineWidth / aRadius / 2.0, aStartAngle + M_PI, 0 ); drawSemiCircle( startPoint, lineWidth / aRadius / 2.0, aStartAngle + M_PI );
drawSemiCircle( endPoint, lineWidth / aRadius / 2.0, aEndAngle, 0 ); drawSemiCircle( endPoint, lineWidth / aRadius / 2.0, aEndAngle );
} }
} }
} }
...@@ -1341,15 +1384,15 @@ void OPENGL_GAL::DrawArc( const VECTOR2D& aCenterPoint, double aRadius, double a ...@@ -1341,15 +1384,15 @@ void OPENGL_GAL::DrawArc( const VECTOR2D& aCenterPoint, double aRadius, double a
for( alpha = aStartAngle; ( alpha + alphaIncrement ) < aEndAngle; ) for( alpha = aStartAngle; ( alpha + alphaIncrement ) < aEndAngle; )
{ {
vertex3( middlePoint.x, middlePoint.y, 0.0 ); vertex3( middlePoint.x, middlePoint.y, layerDepth );
vertex3( cos( alpha ), sin( alpha ), 0.0 ); vertex3( cos( alpha ), sin( alpha ), layerDepth );
alpha += alphaIncrement; alpha += alphaIncrement;
vertex3( cos( alpha ), sin( alpha ), 0.0 ); vertex3( cos( alpha ), sin( alpha ), layerDepth );
} }
vertex3( middlePoint.x, middlePoint.y, 0.0 ); vertex3( middlePoint.x, middlePoint.y, layerDepth );
vertex3( cos( alpha ), sin( alpha ), 0.0 ); vertex3( cos( alpha ), sin( alpha ), layerDepth );
vertex3( endPoint.x, endPoint.y, 0.0 ); vertex3( endPoint.x, endPoint.y, layerDepth );
end(); end();
} }
...@@ -1391,6 +1434,8 @@ void OPENGL_GAL::DrawPolygon( const std::deque<VECTOR2D>& aPointList ) ...@@ -1391,6 +1434,8 @@ void OPENGL_GAL::DrawPolygon( const std::deque<VECTOR2D>& aPointList )
// Any non convex polygon needs to be tesselated // Any non convex polygon needs to be tesselated
// for this purpose the GLU standard functions are used // for this purpose the GLU standard functions are used
setShader( SHADER_NONE );
GLUtesselator* tesselator = gluNewTess(); GLUtesselator* tesselator = gluNewTess();
typedef std::vector<OGLPOINT> OGLPOINTS; typedef std::vector<OGLPOINT> OGLPOINTS;
...@@ -1624,18 +1669,27 @@ int OPENGL_GAL::BeginGroup() ...@@ -1624,18 +1669,27 @@ int OPENGL_GAL::BeginGroup()
void OPENGL_GAL::EndGroup() void OPENGL_GAL::EndGroup()
{ {
wxASSERT_MSG( curVboItem->GetSize() != 0, #ifdef __WXDEBUG__
"OPENGL_GAL::EndGroup: Tried to add group that contains nothing" ); if( curVboItem->GetSize() != 0 )
{
wxLogDebug( wxT( "Tried to add group that contains nothing" ) );
}
#endif /* __WXDEBUG__ */
vboSize += curVboItem->GetSize(); vboSize += curVboItem->GetSize();
curVboItem = NULL;
isGrouping = false; isGrouping = false;
} }
void OPENGL_GAL::DeleteGroup( int aGroupNumber ) void OPENGL_GAL::DeleteGroup( int aGroupNumber )
{ {
wxASSERT_MSG( aGroupNumber < vboItems.size(), #ifdef __WXDEBUG__
"OPENGL_GAL::DeleteGroup: Tried to delete not existing group" ); if( (unsigned) aGroupNumber < vboItems.size() )
{
wxLogDebug( wxT( "Tried to delete not existing group" ) );
}
#endif /* __WXDEBUG__ */
std::deque<VBO_ITEM*>::iterator it = vboItems.begin(); std::deque<VBO_ITEM*>::iterator it = vboItems.begin();
std::advance( it, aGroupNumber ); std::advance( it, aGroupNumber );
...@@ -1962,7 +2016,7 @@ void OPENGL_GAL::DrawGridLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEnd ...@@ -1962,7 +2016,7 @@ void OPENGL_GAL::DrawGridLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEnd
VECTOR2D point4 = aEndPoint - perpendicularVector; VECTOR2D point4 = aEndPoint - perpendicularVector;
if( isUseShader ) if( isUseShader )
selectShader( -1 ); shader.Deactivate();
// Set color // Set color
glColor4d( gridColor.r, gridColor.g, gridColor.b, gridColor.a ); glColor4d( gridColor.r, gridColor.g, gridColor.b, gridColor.a );
......
/* /*
* This program source code file is part of KICAD, a free EDA CAD application. * This program source code file is part of KICAD, a free EDA CAD application.
* *
* Copyright (C) 2013 Tomasz Wlostowski <tomasz.wlostowski@cern.ch> * Copyright (C) 2013 CERN
* @author Maciej Suminski <maciej.suminski@cern.ch>
* *
* Fragment shader * Fragment shader
* *
...@@ -24,18 +25,48 @@ ...@@ -24,18 +25,48 @@
*/ */
#version 120 #version 120
//#pragma debug(on)
varying float aspect; // Shader types
const float SHADER_LINE = 1.0;
const float SHADER_FILLED_CIRCLE = 2.0;
const float SHADER_STROKED_CIRCLE = 3.0;
void main() varying in vec4 shaderParams;
void filledCircle( vec2 aCoord )
{ {
vec2 v = abs( gl_TexCoord[0].xy - vec2( 0.5, 0.5 ) ) * 2.0 - vec2( aspect, 0.0 ); if( dot( aCoord, aCoord ) < 1.0 )
vec2 d = vec2( v.x / ( 1.0 - aspect ), v.y ); gl_FragColor = gl_Color;
else
discard;
}
if( v.x <= 0.0 || (dot( d, d ) < 1.0 ) )
void strokedCircle( vec2 aCoord, float aWidth )
{
if( ( dot( aCoord, aCoord ) < 1.0 ) &&
( dot( aCoord, aCoord ) > aWidth * aWidth ) )
gl_FragColor = gl_Color; gl_FragColor = gl_Color;
else else
discard; discard;
}
// gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0); void main()
{
if( shaderParams[0] == SHADER_FILLED_CIRCLE )
{
filledCircle( vec2( shaderParams[1], shaderParams[2] ) );
}
else if( shaderParams[0] == SHADER_STROKED_CIRCLE )
{
strokedCircle( vec2( shaderParams[1], shaderParams[2] ), shaderParams[3] );
}
else
{
// Simple pass-through
gl_FragColor = gl_Color;
}
} }
/* /*
* This program source code file is part of KICAD, a free EDA CAD application. * This program source code file is part of KICAD, a free EDA CAD application.
* *
* Copyright (C) 2012 Torsten Hueter, torstenhtr <at> gmx.de * Copyright (C) 2013 CERN
* Copyright (C) 2012 Kicad Developers, see change_log.txt for contributors. * @author Maciej Suminski <maciej.suminski@cern.ch>
* *
* Vertex shader * Vertex shader
* *
...@@ -24,12 +24,42 @@ ...@@ -24,12 +24,42 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/ */
// This shader requires GLSL 1.2
#version 120 #version 120
// Shader types
const float SHADER_LINE = 1.0;
const float SHADER_FILLED_CIRCLE = 2.0;
const float SHADER_STROKED_CIRCLE = 3.0;
attribute vec4 attrShaderParams;
varying out vec4 shaderParams;
void main() void main()
{ {
// Simple pass-through // Pass attributes to the fragment shader
gl_Position = gl_Vertex; shaderParams = attrShaderParams;
if( shaderParams[0] == SHADER_LINE )
{
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 < 1.0 )
scale = 1.0 / ( worldScale * lineWidth );
else
scale = 1.0;
gl_Position = gl_ModelViewProjectionMatrix *
( gl_Vertex + vec4( shaderParams.yz * scale, 0.0, 0.0 ) );
}
else
{
// Pass through the coordinates like in the fixed pipeline
gl_Position = ftransform();
}
gl_FrontColor = gl_Color; gl_FrontColor = gl_Color;
} }
/*
* This program source code file is part of KICAD, a free EDA CAD application.
*
* Copyright (C) 2012 Torsten Hueter, torstenhtr <at> gmx.de
* Copyright (C) 2012 Kicad Developers, see change_log.txt for contributors.
*
* 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
*/
// This shader requires GLSL 1.2
#version 120
// Input variables
flat varying vec4 center_;
flat varying vec2 radius_;
flat varying vec4 colorA_;
flat varying vec4 colorB_;
void main( void )
{
// Compute the distance from the circle edge
float distA = distance( center_, gl_FragCoord ) - radius_.y;
float distB = radius_.x - distance( center_, gl_FragCoord );
// Limit the range to [ 0 .. 1 ]
if( distA < 0 ) distA = 0;
if( distA > 1 ) distA = 1;
if( distB < 0 ) distB = 0;
if( distB > 1 ) distB = 1;
// Points with a larger distance from the edge are set deeper
gl_FragDepth = gl_FragCoord.z + distA * 0.001 + distB * 0.001;
// Compute the color
vec4 color;
color.r = colorA_.r;
color.g = colorA_.g;
color.b = colorA_.b;
color.a = colorA_.a * ( 1 - distA ) * ( 1 - distB );
// Now output the edge fragment color
gl_FragColor = color;
}
/*
* This program source code file is part of KICAD, a free EDA CAD application.
*
* Copyright (C) 2012 Torsten Hueter, torstenhtr <at> gmx.de
* Copyright (C) 2012 Kicad Developers, see change_log.txt for contributors.
*
* Geometry 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
*/
// This shader requires GLSL 1.2
#version 120
#extension GL_EXT_geometry_shader4: enable
#extension GL_EXT_gpu_shader4: enable
uniform float viewPortX2;
uniform float viewPortY2;
flat varying vec4 center_;
flat varying vec2 radius_;
flat varying vec4 colorA_;
const float PI = 3.141592654;
const float EPSILON = 0.01;
const float smallestValue = 1.175494351e-38;
const int SEGMENTS = 16;
const float PIXEL_EXTEND = 1.5;
void main()
{
vec4 center = gl_PositionIn[0];
vec4 radius = gl_PositionIn[1];
center_ = gl_ModelViewProjectionMatrix * center;
// Compute the outer and inner radius in screen coordinates
// This could be further optimized
radius_.x = ( gl_ModelViewProjectionMatrix * vec4(radius.x, 0, 0, 1) ).x;
radius_.x = abs( radius_.x - (gl_ModelViewProjectionMatrix * vec4(0, 0, 0, 1) ).x ) * viewPortX2;
radius_.y = ( gl_ModelViewProjectionMatrix * vec4(radius.y, 0, 0, 1) ).x;
radius_.y = abs( radius_.y - (gl_ModelViewProjectionMatrix * vec4(0, 0, 0, 1) ).x ) * viewPortX2;
// Compute the center point in screen coordinates
center_.x = center_.x * viewPortX2 + viewPortX2;
center_.y = center_.y * viewPortY2 + viewPortY2;
// Compute the extend value, first make sure that the outline is inside the triangles and second add
// a margin for one pixel for smooth edges
float extendInner = 1.0;
float extendOuter = 0;
if( radius_.y > smallestValue )
{
extendOuter += PIXEL_EXTEND / radius_.y;
}
extendOuter += 1.0 / cos( PI / SEGMENTS );
colorA_ = gl_FrontColorIn[0];
// Create a quad strip for the outer circle edge
for( float alpha = 0, inc = 2 * PI / SEGMENTS, limit = 2 * PI + EPSILON;
alpha < limit; alpha += inc )
{
gl_Position = gl_ModelViewProjectionMatrix *
vec4( center.x + extendInner * radius.y * cos( alpha ),
center.y + extendInner * radius.y * sin( alpha ), center.zw );
EmitVertex();
gl_Position = gl_ModelViewProjectionMatrix *
vec4( center.x + extendOuter * radius.y * cos( alpha ),
center.y + extendOuter * radius.y * sin( alpha ), center.zw );
EmitVertex();
}
EndPrimitive();
if( radius.x > 0 )
{
extendInner = cos( PI / SEGMENTS ) - PIXEL_EXTEND / radius_.x;
if( extendInner < 0.0 )
{
extendInner = 0;
}
extendOuter = 1.0 / cos( PI / SEGMENTS);
// Create a quad strip for the inner circle edge
for( float alpha = 0, inc = 2 * PI / SEGMENTS, limit = 2 * PI + EPSILON;
alpha < limit; alpha += inc )
{
gl_Position = gl_ModelViewProjectionMatrix *
vec4( center.x + extendOuter * radius.x * cos( alpha ),
center.y + extendOuter * radius.x * sin( alpha ), center.zw );
EmitVertex();
gl_Position = gl_ModelViewProjectionMatrix *
vec4( center.x + extendInner * radius.x * cos( alpha ),
center.y + extendInner * radius.x * sin( alpha ), center.zw );
EmitVertex();
}
EndPrimitive();
}
}
/*
* This program source code file is part of KICAD, a free EDA CAD application.
*
* Copyright (C) 2012 Torsten Hueter, torstenhtr <at> gmx.de
* Copyright (C) 2012 Kicad Developers, see change_log.txt for contributors.
*
* 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
*/
// This shader requires GLSL 1.2
#version 120
void main()
{
// Simple pass-through
gl_Position = gl_Vertex;
gl_FrontColor = gl_Color;
}
/*
* This program source code file is part of KICAD, a free EDA CAD application.
*
* Copyright (C) 2012 Torsten Hueter, torstenhtr <at> gmx.de
* Copyright (C) 2012 Kicad Developers, see change_log.txt for contributors.
*
* 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
#extension GL_EXT_gpu_shader4: enable
varying float dist;
void main()
{
float d = dist;
gl_FragDepth = gl_FragCoord.z + d * 0.001;
gl_FragColor = vec4( gl_Color.rgb, gl_Color.a * ( 1 - d ) );
}
/*
* This program source code file is part of KICAD, a free EDA CAD application.
*
* Copyright (C) 2012 Torsten Hueter, torstenhtr <at> gmx.de
* Copyright (C) 2012 Kicad Developers, see change_log.txt for contributors.
*
* Geometry 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
#extension GL_EXT_geometry_shader4: enable
#extension GL_EXT_gpu_shader4: enable
uniform float viewPortX2;
uniform float viewPortY2;
varying float dist;
void main()
{
// Compute the transformed start and end points
vec2 startPoint = gl_PositionIn[0].xy;
vec2 endPoint = gl_PositionIn[1].xy;
float lineWidth = gl_PositionIn[1].z;
// Compute vector start -> end
vec2 startEndVector = endPoint.xy - startPoint.xy;
float lineLength = distance( startPoint, endPoint );
float scale = 0.0;
if( lineLength > 0.0 )
{
scale = 0.5 * lineWidth / lineLength;
}
else
{
scale = 0.0;
}
// Compute the edge points of the line
vec2 perpendicularVector = scale * vec2( -startEndVector.y, startEndVector.x );
vec2 point1 = startPoint + perpendicularVector;
vec2 point2 = startPoint - perpendicularVector;
vec2 point3 = endPoint + perpendicularVector;
vec2 point4 = endPoint - perpendicularVector;
vec4 point1T = gl_ModelViewProjectionMatrix * vec4( point1, gl_PositionIn[0].zw );
vec4 point2T = gl_ModelViewProjectionMatrix * vec4( point2, gl_PositionIn[0].zw );
vec4 point3T = gl_ModelViewProjectionMatrix * vec4( point3, gl_PositionIn[0].zw );
vec4 point4T = gl_ModelViewProjectionMatrix * vec4( point4, gl_PositionIn[0].zw );
// Construct the quad for the middle
gl_FrontColor = gl_FrontColorIn[0];
dist = 0;
gl_Position = point1T;
EmitVertex();
dist = 0;
gl_Position = point2T;
EmitVertex();
dist = 0;
gl_Position = point3T;
EmitVertex();
dist = 0;
gl_Position = point4T;
EmitVertex();
EndPrimitive();
// Compute the perpendicular vector with 1 pixel width
vec2 v = point1T.xy - point3T.xy;
vec4 onePix = 0.5 * vec4( -v.y, v.x, 0, 0 );
onePix *= 1.0 / sqrt( dot( onePix, onePix ) );
onePix.x *= 1.0 / viewPortX2;
onePix.y *= 1.0 / viewPortY2;
gl_FrontColor = gl_FrontColorIn[0];
dist = 1;
gl_Position = point1T + onePix;
EmitVertex();
dist = 1;
gl_Position = point3T + onePix;
EmitVertex();
dist = 0;
gl_Position = point1T;
EmitVertex();
dist = 0;
gl_Position = point3T;
EmitVertex();
EndPrimitive();
dist = 1;
gl_Position = point2T - onePix;
EmitVertex();
dist = 1;
gl_Position = point4T - onePix;
EmitVertex();
dist = 0;
gl_Position = point2T;
EmitVertex();
dist = 0;
gl_Position = point4T;
EmitVertex();
EndPrimitive();
}
/*
* This program source code file is part of KICAD, a free EDA CAD application.
*
* Copyright (C) 2013 Tomasz Wlostowski <tomasz.wlostowski@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
varying float aspect;
void main()
{
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
gl_FrontColor = gl_Color;
gl_TexCoord[0] = gl_MultiTexCoord0;
aspect = gl_Normal.x;
}
...@@ -40,6 +40,9 @@ VBO_ITEM::VBO_ITEM() : ...@@ -40,6 +40,9 @@ VBO_ITEM::VBO_ITEM() :
m_isDirty( true ), m_isDirty( true ),
m_transform( NULL ) m_transform( NULL )
{ {
// By default no shader is used
m_shader[0] = 0;
// Prepare a block for storing vertices & indices // Prepare a block for storing vertices & indices
useNewBlock(); useNewBlock();
} }
...@@ -50,7 +53,7 @@ VBO_ITEM::~VBO_ITEM() ...@@ -50,7 +53,7 @@ VBO_ITEM::~VBO_ITEM()
if( m_isDirty ) if( m_isDirty )
{ {
// Data is still stored in blocks // Data is still stored in blocks
std::list<GLfloat*>::const_iterator v_it, v_end; std::list<VBO_VERTEX*>::const_iterator v_it, v_end;
for( v_it = m_vertBlocks.begin(), v_end = m_vertBlocks.end(); v_it != v_end; ++v_it ) for( v_it = m_vertBlocks.begin(), v_end = m_vertBlocks.end(); v_it != v_end; ++v_it )
delete[] *v_it; delete[] *v_it;
...@@ -75,24 +78,27 @@ void VBO_ITEM::PushVertex( const GLfloat* aVertex ) ...@@ -75,24 +78,27 @@ void VBO_ITEM::PushVertex( const GLfloat* aVertex )
if( m_transform != NULL ) if( m_transform != NULL )
{ {
// Apply transformations // Apply transformations
// X, Y, Z coordinates // X, Y, Z coordinates
glm::vec4 origVertex( aVertex[0], aVertex[1], aVertex[2], 1.0f ); glm::vec4 vertex( aVertex[0], aVertex[1], aVertex[2], 1.0f );
glm::vec4 transVertex = *m_transform * origVertex; vertex = *m_transform * vertex;
// Replace only coordinates, leave color as it is // Replace only coordinates, leave color as it is
memcpy( m_vertPtr, &transVertex[0], CoordSize ); memcpy( &m_vertPtr->struc.coord, &vertex[0], CoordByteSize );
} }
else else
{ {
// Add the new vertex // Add the new vertex
memcpy( m_vertPtr, aVertex, CoordSize ); memcpy( &m_vertPtr->struc.coord, aVertex, CoordByteSize );
} }
// Apply currently used color // Apply currently used color
memcpy( m_vertPtr + ColorOffset, m_color, ColorSize ); memcpy( &m_vertPtr->struc.color, m_color, ColorByteSize );
// Apply currently used shader
memcpy( &m_vertPtr->struc.shader, m_shader, ShaderByteSize );
// Move to the next free space // Move to the next free space
m_vertPtr += VertStride; m_vertPtr++;
// Add the new index // Add the new index
*m_indPtr = m_offset + m_size; *m_indPtr = m_offset + m_size;
...@@ -177,10 +183,10 @@ void VBO_ITEM::ChangeColor( const COLOR4D& aColor ) ...@@ -177,10 +183,10 @@ void VBO_ITEM::ChangeColor( const COLOR4D& aColor )
for( int i = 0; i < m_size; ++i ) for( int i = 0; i < m_size; ++i )
{ {
memcpy( vertexPtr, newColor, ColorSize ); memcpy( vertexPtr, newColor, ColorByteSize );
// Move on to the next vertex // Move on to the next vertex
vertexPtr += VertStride; vertexPtr++;
} }
} }
...@@ -194,6 +200,12 @@ void VBO_ITEM::UseColor( const COLOR4D& aColor ) ...@@ -194,6 +200,12 @@ void VBO_ITEM::UseColor( const COLOR4D& aColor )
} }
void VBO_ITEM::UseShader( const GLfloat* aShader )
{
memcpy( m_shader, aShader, ShaderByteSize );
}
/* /*
// TODO // TODO
void SetVbo( int aVboId ) void SetVbo( int aVboId )
...@@ -209,8 +221,8 @@ int GetVbo() const ...@@ -209,8 +221,8 @@ int GetVbo() const
void VBO_ITEM::useNewBlock() void VBO_ITEM::useNewBlock()
{ {
GLfloat* newVertBlock = new GLfloat[BLOCK_SIZE * VertStride]; VBO_VERTEX* newVertBlock = new VBO_VERTEX[BLOCK_SIZE];
GLuint* newIndBlock = new GLuint[BLOCK_SIZE]; GLuint* newIndBlock = new GLuint[BLOCK_SIZE];
m_vertPtr = newVertBlock; m_vertPtr = newVertBlock;
m_indPtr = newIndBlock; m_indPtr = newIndBlock;
...@@ -233,16 +245,16 @@ void VBO_ITEM::prepareFinal() ...@@ -233,16 +245,16 @@ void VBO_ITEM::prepareFinal()
GLfloat* vertPtr = m_vertices; GLfloat* vertPtr = m_vertices;
// Copy blocks of vertices one after another to m_vertices // Copy blocks of vertices one after another to m_vertices
std::list<GLfloat*>::const_iterator v_it; std::list<VBO_VERTEX*>::const_iterator v_it;
for( v_it = m_vertBlocks.begin(); *v_it != m_vertBlocks.back(); ++v_it ) for( v_it = m_vertBlocks.begin(); *v_it != m_vertBlocks.back(); ++v_it )
{ {
memcpy( vertPtr, *v_it, BLOCK_SIZE * VertSize ); memcpy( vertPtr, *v_it, BLOCK_SIZE * VertByteSize );
delete[] *v_it; delete[] *v_it;
vertPtr += ( BLOCK_SIZE * VertStride ); vertPtr += ( BLOCK_SIZE * VertStride );
} }
// In the last block we need to copy only used vertices // In the last block we need to copy only used vertices
memcpy( vertPtr, *v_it, ( BLOCK_SIZE - m_spaceLeft ) * VertSize ); memcpy( vertPtr, *v_it, ( BLOCK_SIZE - m_spaceLeft ) * VertByteSize );
if( m_indices ) if( m_indices )
delete m_indices; delete m_indices;
...@@ -256,13 +268,13 @@ void VBO_ITEM::prepareFinal() ...@@ -256,13 +268,13 @@ void VBO_ITEM::prepareFinal()
std::list<GLuint*>::const_iterator i_it; std::list<GLuint*>::const_iterator i_it;
for( i_it = m_indBlocks.begin(); *i_it != m_indBlocks.back(); ++i_it ) for( i_it = m_indBlocks.begin(); *i_it != m_indBlocks.back(); ++i_it )
{ {
memcpy( indPtr, *i_it, BLOCK_SIZE * IndSize ); memcpy( indPtr, *i_it, BLOCK_SIZE * IndByteSize );
delete[] *i_it; delete[] *i_it;
indPtr += ( BLOCK_SIZE * IndStride ); indPtr += ( BLOCK_SIZE * IndStride );
} }
// In the last block we need to copy only used indices // In the last block we need to copy only used indices
memcpy( indPtr, *i_it, ( BLOCK_SIZE - m_spaceLeft ) * IndSize ); memcpy( indPtr, *i_it, ( BLOCK_SIZE - m_spaceLeft ) * IndByteSize );
m_isDirty = false; m_isDirty = false;
} }
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
// OpenGL mathematics library // OpenGL mathematics library
#define GLM_FORCE_RADIANS #define GLM_FORCE_RADIANS
#include <gal/opengl/vbo_item.h> #include <gal/opengl/vbo_item.h>
#include <gal/opengl/shader.h>
// wxWidgets imports // wxWidgets imports
#include <wx/wx.h> #include <wx/wx.h>
...@@ -323,7 +324,6 @@ private: ...@@ -323,7 +324,6 @@ private:
static const int CIRCLE_POINTS = 64; ///< The number of points for circle approximation static const int CIRCLE_POINTS = 64; ///< The number of points for circle approximation
static const int CURVE_POINTS = 32; ///< The number of points for curve approximation static const int CURVE_POINTS = 32; ///< The number of points for curve approximation
static const int SHADER_NUMBER = 2; ///< Number of the used shaders
static const double MITER_LIMIT = 1.5; ///< Limit for mitered edges ( * lineWidth ) static const double MITER_LIMIT = 1.5; ///< Limit for mitered edges ( * lineWidth )
/// This factor is used to for correct merging of antialiased edges, /// This factor is used to for correct merging of antialiased edges,
...@@ -365,7 +365,18 @@ private: ...@@ -365,7 +365,18 @@ private:
GLUtesselator* tesselator; ///< Pointer to the tesselator GLUtesselator* tesselator; ///< Pointer to the tesselator
// Shader // Shader
std::deque<SHADER> shaderList; ///< List of the shaders // Possible types of shaders
typedef enum
{
SHADER_NONE = 0,
SHADER_LINE,
SHADER_FILLED_CIRCLE,
SHADER_STROKED_CIRCLE,
} SHADER_TYPE;
SHADER shader; ///< There is only one shader used for different objects
int shaderAttrib; ///< Location of shader attributes (for glVertexAttribPointer)
std::string shaderPath; ///< Location of shader files
// Cursor // Cursor
int cursorSize; ///< Size of the cursor in pixels int cursorSize; ///< Size of the cursor in pixels
...@@ -391,8 +402,6 @@ private: ...@@ -391,8 +402,6 @@ private:
bool isShaderEnabled; ///< Are the shaders enabled? bool isShaderEnabled; ///< Are the shaders enabled?
bool isUseShader; ///< Should the shaders be used? bool isUseShader; ///< Should the shaders be used?
bool isGrouping; ///< Was a group started? bool isGrouping; ///< Was a group started?
int currentShader; ///< ID of the shader currently in use
std::string shaderPath;
/** /**
* @brief Draw a semi circle (used for line caps). * @brief Draw a semi circle (used for line caps).
...@@ -400,11 +409,9 @@ private: ...@@ -400,11 +409,9 @@ private:
* @param aCenterPoint is the center point. * @param aCenterPoint is the center point.
* @param aRadius is the radius of the semi-circle. * @param aRadius is the radius of the semi-circle.
* @param aAngle is the angle of the semi-circle. * @param aAngle is the angle of the semi-circle.
* @param ADepthOffset is the relative depth of the semi-circle.
* *
*/ */
void drawSemiCircle( const VECTOR2D& aCenterPoint, double aRadius, double aAngle, void drawSemiCircle( const VECTOR2D& aCenterPoint, double aRadius, double aAngle );
double aDepthOffset );
/// Compute the points of a unit circle. /// Compute the points of a unit circle.
void computeUnitCircle(); void computeUnitCircle();
...@@ -506,8 +513,7 @@ private: ...@@ -506,8 +513,7 @@ private:
* @param aEndPoint is the end point of the line. * @param aEndPoint is the end point of the line.
* @param aDepthOffset is the relative depth of the line cap. * @param aDepthOffset is the relative depth of the line cap.
*/ */
inline void drawLineCap( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint, inline void drawLineCap( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint );
double aDepthOffset );
///< OpenGL replacement functions (that are working both in immediate and VBO modes) ///< OpenGL replacement functions (that are working both in immediate and VBO modes)
/** /**
...@@ -561,13 +567,23 @@ private: ...@@ -561,13 +567,23 @@ private:
*/ */
inline void color4( const COLOR4D& aColor ); inline void color4( const COLOR4D& aColor );
inline void selectShader( int aIndex ); /**
* @brief Function that sets shader and its parameters for the currently used VBO_ITEM.
/// @copydoc GAL::DrawRoundedSegment() * It should be used before adding any vertices that have to be shaded.
void drawRoundedSegment( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint, double aWidth, * @param aShader is the type of shader used for vertices.
bool aStroke = false, bool aGlBegin = false ); * @param aParam[1..3] are shader's parameters. Their meaning depends on the type of used shader.
* For more information you may check shaders' source code.
*/
inline void setShader( SHADER_TYPE aShader, GLfloat aParam1 = 0.0f,
GLfloat aParam2 = 0.0f, GLfloat aParam3 = 0.0f )
{
if( isUseShader && isGrouping )
{
const GLfloat shader[] = { aShader, aParam1, aParam2, aParam3 };
curVboItem->UseShader( shader );
}
}
}; };
} // namespace KiGfx } // namespace KiGfx
......
...@@ -34,10 +34,31 @@ ...@@ -34,10 +34,31 @@
#include <gal/opengl/glm/glm.hpp> #include <gal/opengl/glm/glm.hpp>
#include <gal/color4d.h> #include <gal/color4d.h>
#include <cstddef>
#include <list> #include <list>
namespace KiGfx namespace KiGfx
{ {
typedef struct VBO_VERTEX_DATA
{
GLfloat x, y, z; // Coordinates
GLfloat r, g, b, a; // Color
GLfloat shader[4]; // Shader type & params
} VBO_VERTEX_DATA;
typedef struct VBO_VERTEX_STRUCT
{
GLfloat coord[3]; // Coordinates
GLfloat color[4]; // Color
GLfloat shader[4]; // Shader type & params
} VBO_VERTEX_STRUCT;
typedef union VBO_VERTEX
{
VBO_VERTEX_DATA data;
VBO_VERTEX_STRUCT struc;
} VBO_VERTEX;
class VBO_ITEM class VBO_ITEM
{ {
...@@ -50,6 +71,7 @@ public: ...@@ -50,6 +71,7 @@ public:
* Adds a single vertex to the VBO_ITEM. Vertex contains information about coordinates and * Adds a single vertex to the VBO_ITEM. Vertex contains information about coordinates and
* colors and has to follow the specified format {X,Y,Z,R,G,B,A}. * colors and has to follow the specified format {X,Y,Z,R,G,B,A}.
* @param aVertex is a vertex to be added. * @param aVertex is a vertex to be added.
* @param aShader is an attribute for shader.
*/ */
void PushVertex( const GLfloat* aVertex ); void PushVertex( const GLfloat* aVertex );
...@@ -60,6 +82,7 @@ public: ...@@ -60,6 +82,7 @@ public:
* coordinates and colors and has to follow the specified format {X,Y,Z,R,G,B,A}. * coordinates and colors and has to follow the specified format {X,Y,Z,R,G,B,A}.
* @param aVertices are vertices to be added. * @param aVertices are vertices to be added.
* @param aSize is an amount of vertices to be added. * @param aSize is an amount of vertices to be added.
* @param aShader is an attribute for shader.
*/ */
void PushVertices( const GLfloat* aVertices, GLuint aSize ); void PushVertices( const GLfloat* aVertices, GLuint aSize );
...@@ -121,26 +144,38 @@ public: ...@@ -121,26 +144,38 @@ public:
*/ */
void UseColor( const COLOR4D& aColor ); void UseColor( const COLOR4D& aColor );
/**
* Function UseShader()
* Sets shader and its parameters used for all added vertices.
* @param aShader is the array that contains shader number followed by its parameters.
*/
void UseShader( const GLfloat* aShader );
///< Functions for getting VBO ids. ///< Functions for getting VBO ids.
//void SetVbo( int aVboId ); //void SetVbo( int aVboId );
//int GetVbo() const; //int GetVbo() const;
///< Data organization information for vertices {X,Y,Z,R,G,B,A}. ///< Data organization information for vertices {X,Y,Z,R,G,B,A} (@see VBO_VERTEX).
// Each vertex consists of 7 floats, but it is padded to 8 static const int VertByteSize = sizeof(VBO_VERTEX);
static const int VertStride = 8; static const int VertStride = VertByteSize / sizeof(GLfloat);
static const int VertSize = VertStride * sizeof(GLfloat);
static const int CoordStride = 3; static const int CoordStride = sizeof(VBO_VERTEX_STRUCT().coord) / sizeof(GLfloat);
static const int CoordSize = CoordStride * sizeof(GLfloat); static const int CoordByteSize = sizeof(VBO_VERTEX_STRUCT().coord);
// Offset of color data from the beginning of each vertex data // Offset of color data from the beginning of each vertex data
static const int ColorOffset = 3; static const int ColorByteOffset = offsetof( VBO_VERTEX_STRUCT, color );
static const int ColorByteOffset = ColorOffset * sizeof(GLfloat); static const int ColorOffset = ColorByteOffset / sizeof(GLfloat);
static const int ColorStride = 4; static const int ColorStride = sizeof(VBO_VERTEX_STRUCT().color) / sizeof(GLfloat);
static const int ColorSize = ColorStride * sizeof(GLfloat); static const int ColorByteSize = sizeof(VBO_VERTEX_STRUCT().color);
// Shader attributes
static const int ShaderByteOffset = offsetof( VBO_VERTEX_STRUCT, shader );
static const int ShaderOffset = ShaderByteOffset / sizeof(GLfloat);
static const int ShaderStride = sizeof(VBO_VERTEX_STRUCT().shader) / sizeof(GLfloat);
static const int ShaderByteSize = sizeof(VBO_VERTEX_STRUCT().shader);
static const int IndStride = 1; static const int IndStride = 1;
static const int IndSize = IndStride * sizeof(GLuint); static const int IndByteSize = IndStride * sizeof(GLuint);
private: private:
///< VBO ids in which the item is stored. ///< VBO ids in which the item is stored.
...@@ -153,31 +188,30 @@ private: ...@@ -153,31 +188,30 @@ private:
///< Indices of vertices ///< Indices of vertices
GLuint* m_indices; GLuint* m_indices;
///< Lists of blocks ///< Lists of data blocks storing vertices
std::list<GLfloat*> m_vertBlocks; std::list<VBO_VERTEX*> m_vertBlocks;
std::list<GLuint*> m_indBlocks; std::list<GLuint*> m_indBlocks;
///< Pointers to current blocks that can be used for storing data ///< Pointers to current blocks that should be used for storing data
GLfloat* m_vertPtr; VBO_VERTEX* m_vertPtr;
GLuint* m_indPtr; GLuint* m_indPtr;
///< How many vertices can be stored in the current buffer ///< How many vertices can be stored in the current buffer
int m_spaceLeft; int m_spaceLeft;
///< Number of vertices & indices stored in a single block ///< Number of vertices & indices stored in a single block
static const int BLOCK_SIZE = 8; static const int BLOCK_SIZE = 256;
///< Creates a new block for storing vertices data ///< Creates a new block for storing vertices data
void useNewBlock(); void useNewBlock();
///< Prepares a continuous block of data that can be copied to graphics card buffer. ///< Prepares a continuous block of data that can be copied to graphics card buffer.
void prepareFinal(); void prepareFinal();
///< Offset and size of data in VBO. ///< Offset and size of data in VBO.
int m_offset; int m_offset;
int m_size; int m_size;
///< Shader data used for rendering.
int m_shader;
int m_shaderAttrib;
///< Color used for new vertices pushed. ///< Color used for new vertices pushed.
GLfloat m_color[4]; GLfloat m_color[ColorStride];
///< Shader and its parameters used for new vertices pushed
GLfloat m_shader[ShaderStride];
///< Flag telling if the item should be recached in VBO or not. ///< Flag telling if the item should be recached in VBO or not.
bool m_isDirty; bool m_isDirty;
......
...@@ -582,12 +582,12 @@ void PCB_EDIT_FRAME::SwitchCanvas( wxCommandEvent& aEvent ) ...@@ -582,12 +582,12 @@ void PCB_EDIT_FRAME::SwitchCanvas( wxCommandEvent& aEvent )
break; break;
case ID_MENU_CANVAS_CAIRO: case ID_MENU_CANVAS_CAIRO:
m_galCanvas->SwitchBackend( EDA_DRAW_PANEL_GAL::GAL_TYPE_CAIRO, false ); m_galCanvas->SwitchBackend( EDA_DRAW_PANEL_GAL::GAL_TYPE_CAIRO );
UseGalCanvas( true ); UseGalCanvas( true );
break; break;
case ID_MENU_CANVAS_OPENGL: case ID_MENU_CANVAS_OPENGL:
m_galCanvas->SwitchBackend( EDA_DRAW_PANEL_GAL::GAL_TYPE_OPENGL, false ); m_galCanvas->SwitchBackend( EDA_DRAW_PANEL_GAL::GAL_TYPE_OPENGL, true );
UseGalCanvas( true ); UseGalCanvas( true );
break; break;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment