Add supersampling (2x/4x) antialiasing

This commit is contained in:
decimad 2016-12-22 20:02:34 +01:00 committed by Maciej Suminski
parent 02bb410cdb
commit afacee5d96
6 changed files with 206 additions and 7 deletions

View File

@ -53,4 +53,133 @@ namespace KIGFX {
return compositor->CreateBuffer( compositor->GetScreenSize() );
}
namespace {
void draw_fullscreen_primitive()
{
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glBegin(GL_TRIANGLES);
glTexCoord2f(0.0f, 1.0f);
glVertex2f(-1.0f, 1.0f);
glTexCoord2f(0.0f, 0.0f);
glVertex2f(-1.0f, -1.0f);
glTexCoord2f(1.0f, 1.0f);
glVertex2f(1.0f, 1.0f);
glTexCoord2f(1.0f, 1.0f);
glVertex2f(1.0f, 1.0f);
glTexCoord2f(0.0f, 0.0f);
glVertex2f(-1.0f, -1.0f);
glTexCoord2f(1.0f, 0.0f);
glVertex2f(1.0f, -1.0f);
glEnd();
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
}
}
// =========================
// ANTIALIASING_SUPERSAMPLING
// =========================
ANTIALIASING_SUPERSAMPLING::ANTIALIASING_SUPERSAMPLING( OPENGL_COMPOSITOR* aCompositor,
SUPERSAMPLING_MODE aMode )
: compositor( aCompositor ), mode( aMode ), areBuffersCreated( false ),
areShadersCreated( false )
{
}
bool ANTIALIASING_SUPERSAMPLING::Init()
{
if( mode == SUPERSAMPLING_MODE::X4 && !areShadersCreated ) {
x4_shader.reset(new SHADER());
x4_shader->LoadShaderFromStrings( KIGFX::SHADER_TYPE_VERTEX, BUILTIN_SHADERS::ssaa_x4_vertex_shader );
x4_shader->LoadShaderFromStrings( KIGFX::SHADER_TYPE_FRAGMENT, BUILTIN_SHADERS::ssaa_x4_fragment_shader );
x4_shader->Link();
checkGlError( "linking supersampling x4 shader" );
GLint source_parameter = x4_shader->AddParameter( "source" ); checkGlError("getting pass 1 colorTex");
x4_shader->Use(); checkGlError("using pass 1 shader");
x4_shader->SetParameter( source_parameter, 0 ); checkGlError("setting colorTex uniform");
x4_shader->Deactivate(); checkGlError("deactivating pass 2 shader");
areShadersCreated = true;
}
if( areShadersCreated && mode != SUPERSAMPLING_MODE::X4 ) {
x4_shader.reset();
areShadersCreated = false;
}
if( !areBuffersCreated ) {
ssaaMainBuffer = compositor->CreateBuffer();
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
areBuffersCreated = true;
}
return true;
}
VECTOR2U ANTIALIASING_SUPERSAMPLING::GetInternalBufferSize()
{
unsigned int factor = (mode == SUPERSAMPLING_MODE::X2) ? 2 : 4;
return compositor->GetScreenSize() * factor;
}
void ANTIALIASING_SUPERSAMPLING::Begin()
{
compositor->SetBuffer( ssaaMainBuffer );
compositor->ClearBuffer();
}
void ANTIALIASING_SUPERSAMPLING::DrawBuffer( GLuint aBuffer )
{
compositor->DrawBuffer( aBuffer, ssaaMainBuffer );
}
void ANTIALIASING_SUPERSAMPLING::Present()
{
glDisable( GL_BLEND );
glDisable( GL_DEPTH_TEST );
glActiveTexture( GL_TEXTURE0 );
glBindTexture( GL_TEXTURE_2D, compositor->GetBufferTexture( ssaaMainBuffer ) );
compositor->SetBuffer( OPENGL_COMPOSITOR::DIRECT_RENDERING );
if( mode == SUPERSAMPLING_MODE::X4 ) {
x4_shader->Use();
checkGlError ( "activating supersampling x4 shader" );
}
draw_fullscreen_primitive();
if( mode == SUPERSAMPLING_MODE::X4 ) {
x4_shader->Deactivate();
checkGlError ( "deactivating supersampling x4 shader" );
}
}
void ANTIALIASING_SUPERSAMPLING::OnLostBuffers()
{
areBuffersCreated = false;
}
unsigned int ANTIALIASING_SUPERSAMPLING::CreateBuffer()
{
return compositor->CreateBuffer( GetInternalBufferSize() );
}
}

View File

@ -41,6 +41,36 @@ namespace KIGFX {
OPENGL_COMPOSITOR* compositor;
};
enum class SUPERSAMPLING_MODE {
X2,
X4
};
class ANTIALIASING_SUPERSAMPLING : public OPENGL_PRESENTOR {
public:
ANTIALIASING_SUPERSAMPLING(OPENGL_COMPOSITOR* compositor, SUPERSAMPLING_MODE aMode);
bool Init() override;
unsigned int CreateBuffer() override;
VECTOR2U GetInternalBufferSize() override;
void OnLostBuffers() override;
void Begin() override;
void DrawBuffer(GLuint) override;
void Present() override;
private:
OPENGL_COMPOSITOR* compositor;
SUPERSAMPLING_MODE mode;
unsigned int ssaaMainBuffer;
bool areBuffersCreated;
bool areShadersCreated;
std::unique_ptr< SHADER > x4_shader;
};
}
#endif

View File

@ -224,6 +224,38 @@ void main()
)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
varying vec2 texcoord;
uniform sampler2D source;
void main()
{
float step_x = dFdx(texcoord.x)/4.;
float step_y = dFdy(texcoord.y)/4.;
vec4 q00 = texture2D( source, texcoord + vec2(-step_x, -step_y) );
vec4 q01 = texture2D( source, texcoord + vec2( step_x, -step_y) );
vec4 q10 = texture2D( source, texcoord + vec2(-step_x, step_y) );
vec4 q11 = texture2D( source, texcoord + vec2( step_x, step_y) );
gl_FragColor = (q00+q01+q10+q11)/4;
}
)SHADER_SOURCE";
}
}

View File

@ -8,6 +8,9 @@ namespace KIGFX {
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[];
}
}

View File

@ -40,7 +40,7 @@ OPENGL_COMPOSITOR::OPENGL_COMPOSITOR() :
m_initialized( false ), m_curBuffer( 0 ),
m_mainFbo( 0 ), m_depthBuffer( 0 ), m_curFbo( DIRECT_RENDERING )
{
m_antialiasing.reset( new ANTIALIASING_NONE( this ) );
m_antialiasing.reset( new ANTIALIASING_SUPERSAMPLING( this, SUPERSAMPLING_MODE::X4 ) );
}
@ -81,6 +81,8 @@ void OPENGL_COMPOSITOR::Initialize()
bindFb( DIRECT_RENDERING );
m_initialized = true;
m_antialiasing->Init();
}
@ -236,7 +238,6 @@ void OPENGL_COMPOSITOR::SetBuffer( unsigned int aBufferHandle )
}
void OPENGL_COMPOSITOR::ClearBuffer()
{
assert( m_initialized );
@ -255,19 +256,19 @@ void OPENGL_COMPOSITOR::Begin()
m_antialiasing->Begin();
}
void OPENGL_COMPOSITOR::DrawBuffer(unsigned int aBufferHandle)
void OPENGL_COMPOSITOR::DrawBuffer( unsigned int aBufferHandle )
{
m_antialiasing->DrawBuffer( aBufferHandle );
}
void OPENGL_COMPOSITOR::DrawBuffer(unsigned int aSourceHandle, unsigned int aDestHandle)
void OPENGL_COMPOSITOR::DrawBuffer( unsigned int aSourceHandle, unsigned int aDestHandle )
{
assert( m_initialized );
assert( aSourceHandle != 0 && aSourceHandle <= usedBuffers() );
assert (aDestHandle <= usedBuffers() );
// Switch to the main framebuffer and blit the scene
bindFb( aDestHandle );
// Switch to the destination buffer and blit the scene
SetBuffer ( aDestHandle );
// Depth test has to be disabled to make transparency working
glDisable( GL_DEPTH_TEST );

View File

@ -299,6 +299,10 @@ void OPENGL_GAL::BeginDrawing()
isBitmapFontInitialized = true;
}
// Something betreen BeginDrawing and EndDrawing seems to depend on
// this texture unit being active, but it does not assure it itself.
glActiveTexture(GL_TEXTURE0);
// Unbind buffers - set compositor for direct drawing
compositor->SetBuffer( OPENGL_COMPOSITOR::DIRECT_RENDERING );
@ -332,7 +336,7 @@ void OPENGL_GAL::EndDrawing()
compositor->DrawBuffer( mainBuffer );
compositor->DrawBuffer( overlayBuffer );
compositor->Present();
blitCursor();
//blitCursor();
SwapBuffers();
GL_CONTEXT_MANAGER::Get().UnlockCtx( glPrivContext );