How to make antialiased lines without addons?

Hello everyone
I am fairly new to oF and while I am generally having fun with it, something that confuses me a lot is how to get antialiased lines. Using ofPolyline I have tried without any extras, with ofEnableAntialiasing() and ofEnableSmoothing() both in the setup() method. Nothing seems to help though or make any difference.

Is there some kind of secret sauce or settings combination not apparant in the documentation which makes it possible to work with antialiased lines?

For reference I am using Arch Linux running oF in Xorg using of_v20200405_linux64gcc6_release and using ofSetupOpenGL(1024,768,OF_WINDOW) in my main function.

below is a screenshot of my failed attempt

Here’s the code used

void ofApp::setup() {

  ofBackground(0, 0, 0);
  ofEnableAntiAliasing();
  ofEnableSmoothing();

  float i = 0;
  while (i < TWO_PI) { // make a heart
    float r =
        (2 - 2 * sin(i) + sin(i) * sqrt(abs(cos(i))) / (sin(i) + 1.4)) * -80;
    float x = ofGetWidth() / 2 + cos(i) * r;
    float y = ofGetHeight() / 2 + sin(i) * r;
    line.addVertex(ofVec3f(x, y, 0));
    i += 0.005 * HALF_PI * 0.5;
  }
  line.close(); // close the shape
}

Hi, works for me, although it works better with smooting on and antialiasing off. No idea why. I tested this on macos so it might be different for you in linux.
Use the following to test.
Use keys a and s to toggle antialiasing and smoothing, respectively.

ofApp.h

#pragma once

#include "ofMain.h"

class ofApp : public ofBaseApp{

	public:
		void setup();
		void update();
		void draw();

		void keyPressed(int key);


	ofPolyline line;
	bool bSmoothing = true;
	bool bAntialiasing = true;
};

ofApp.cpp

#include "ofApp.h"

//--------------------------------------------------------------
void ofApp::setup(){
	

	  ofBackground(0, 0, 0);
	  ofEnableAntiAliasing();
	  ofEnableSmoothing();

	  float i = 0;
	  while (i < TWO_PI) { // make a heart
		float r =
			(2 - 2 * sin(i) + sin(i) * sqrt(abs(cos(i))) / (sin(i) + 1.4)) * -80;
		float x = ofGetWidth() / 2 + cos(i) * r;
		float y = ofGetHeight() / 2 + sin(i) * r;
		line.addVertex(ofVec3f(x, y, 0));
		i += 0.005 * HALF_PI * 0.5;
	  }
	  line.close(); // close the shape
	
}

//--------------------------------------------------------------
void ofApp::update(){

}

//--------------------------------------------------------------
void ofApp::draw(){
	line.draw();
	
	stringstream ss;
	ss << "Smoothing : " << boolalpha << bSmoothing << "\n";
	ss << "Antialiasing : " << boolalpha << bAntialiasing;
	ofDrawBitmapString(ss.str(), 20, 20	);
}

//--------------------------------------------------------------
void ofApp::keyPressed(int key){
	if(key == 'a')
	{
		if(bAntialiasing){
			ofDisableAntiAliasing();
		}else{
			ofEnableAntiAliasing();
		}
		bAntialiasing ^= true;
	}
	else
	if(key == 's')
	{
		if(bSmoothing){
			ofDisableSmoothing();
		}else{
			ofEnableSmoothing();
		}
		bSmoothing ^= true;
	}
}
1 Like

Thanks! This doesn’t help here but I notice some improvement whent the settings are off as you mention. I need to try on MacOS to compare. Would be terrible if this was a linux bug!

Or is there an alternative way of drawing lines which has better aliasing (in Linux) ?

If you’re in 2D you can try the cairo renderer

Also make an fbo and set numsamples = 16 like:

    ofFbo fbo; //in ur .h
    //in setup()
    ofFboSettings s;
    s.width = ofGetWidth();
    s.height = ofGetHeight();
    s.numSamples = 16;
    fbo.allocate(s);

    //in draw()
    fbo.begin();
    ofClear(0, 255);
    line.draw();
    fbo.end();
    fbo.draw(0, 0);
1 Like

The problem with that approach is that it would be excesively slow, as cairo does not use the gpu, afaik.

1 Like

I have no idea.
@arturo might have a better answer

Oh ok, been a long time since ive used it!

Sorry for necro bumping this, but has anyone gotten any good results with this recently? Still dreaming of making crisp, thin lines without fuzzy edges. I’m on MacOS now and have the same issue here it seems.

in case it’s helpful, for 2d lines I sometimes use Cairo, where you draw lines into an image. I don’t find it that slow but depends on what you are trying to do. it’s very crisp and you can adjust line width well beyond what OpenGL can do. We have cairo internally (you can render cairo into a texture) – here’s an example of what I mean

in ofApp.h:

shared_ptr<ofBaseGLRenderer> opengl;
      shared_ptr<ofCairoRenderer> cairo;
      ofTexture render;

and in ofApp.cpp

void ofApp::setup(){

    opengl = ofGetGLRenderer();
    cairo = make_shared<ofCairoRenderer>();
    cairo->setupMemoryOnly(ofCairoRenderer::IMAGE);
    render.allocate(ofGetWidth(), ofGetHeight(), GL_RGBA);
}

//--------------------------------------------------------------
void ofApp::update(){

}

//--------------------------------------------------------------
void ofApp::draw(){

    ofSetCurrentRenderer(cairo);
    
    ofSeedRandom(mouseX*100);
    
    cairo_set_line_cap(cairo->getCairoContext(), CAIRO_LINE_CAP_ROUND);
    ofBackground(ofColor::black);
   
    for (int i = 0; i < 10; i++){
        ofSetColor(ofRandom(0,255));
        cairo_set_line_width(cairo->getCairoContext(), ofRandom(1,100));
        ofLine(ofRandom(0, ofGetWidth()),
               ofRandom(0,ofGetHeight()),
               ofRandom(0,ofGetWidth()),
               ofRandom(0,ofGetHeight()));
    }
    ofSetCurrentRenderer(opengl);
    render.loadData(cairo->getImageSurfacePixels());
    render.draw(0,0,ofGetWidth(), ofGetHeight());
    
}

zip attached:
cairoTest.zip (2.7 KB)

2 Likes

This works great for me. Thanks so much Zach!!!