When using a draw_handler to draw bgl elements to a screen as with GL_POLYGON or GL_LINE_LOOP, are there any bgl flags which can be enabled to invoke antialiasing or will this always require a much more complicated solution?

I'm aware of GL_POLYGON_SMOOTH, GL_POLYGON_SMOOTH_HINT, GL_LINE_SMOOTH, and GL_LINE_SMOOTH_HINT but enabling them before or after using GL_POLYGON or GL_LINE_LOOP doesn't have any affect. Has anyone personally accomplished antialiasing using bgl in Blender Python? If so, could you please show me how?

import bpy,bgl,blf


def draw_callback_px(self, context):

    #Can anything go here to invoke antialiasing?
    bgl.glEnable(bgl.GL_POLYGON_SMOOTH)
    bgl.glEnable(bgl.GL_POLYGON_SMOOTH_HINT)

    bgl.glBegin(bgl.GL_POLYGON)

    #Should flags go here?
    for x, y in self.mouse_path:
        bgl.glVertex2i(x, y)

    #How about here?
    bgl.glEnd()    


#How about an antialiasing function involving
#multi-sampling, bgl texture (or some other) 
#functions etc.. Anyone know how to do this?

class ModalDrawOperator(bpy.types.Operator):
    bl_idname = "object.modal_operator"
    bl_label = "Simple Modal Operator"

    def modal(self, context, event):
        context.area.tag_redraw()

        if event.type == 'MOUSEMOVE':
            self.mouse_path.append((event.mouse_region_x, event.mouse_region_y))

        if event.type in ['LEFTMOUSE','RIGHTMOUSE','ESC']:
            context.space_data.draw_handler_remove(self._handle, 'WINDOW')
            return {'FINISHED'}

        return {'RUNNING_MODAL'}


    def invoke(self, context, event):
        self.mouse_path = []

        args = (self, context)
        self._handle = context.space_data.draw_handler_add(
        draw_callback_px, args, 'WINDOW', 'POST_PIXEL')

        context.window_manager.modal_handler_add(self)
        return {'RUNNING_MODAL'}


bpy.utils.register_class(ModalDrawOperator)
bpy.ops.object.modal_operator('INVOKE_DEFAULT')
up vote 1 down vote accepted

Turns out any kind of smoothing you want to use with GL_POLYGON_SMOOTH, GL_LINE_SMOOTH etc. (antialiasing simple shapes) requires GL_BLEND also be enabled.

I discovered that if you're using GL_POLYGON with GL_POLYGON_SMOOTH enabled, you get weird breaks in your mesh shapes. For this reason it's best to leave GL_POLYGON_SMOOTH off, then surround the shape created with GL_POLYGON with a line from GL_POLYGON_LOOP and then enable GL_LINE_SMOOTH. This gives the appearance of antialiasing around the shape without the weird breaks (demo in code below).

import bpy,bgl


def draw_callback_px(self, context):

    #Set color to white.
    bgl.glColor4f(1, 1, 1, 1)

    #Using polygon smoothing alone creates
    #lines through shape... better to leave
    #off and just smooth outer line.
    #bgl.glEnable(bgl.GL_POLYGON_SMOOTH)

    #GL_BLEND must be enabled for any
    #smoothing to work.
    bgl.glEnable(bgl.GL_BLEND)
    bgl.glEnable(bgl.GL_LINE_SMOOTH)


    #Can't just stack GL_POLYGON
    #and GL_LINE_LOOP
    bgl.glBegin(bgl.GL_POLYGON)
    for x, y in self.mouse_path:
        bgl.glVertex2f(x, y)
    bgl.glEnd()

    bgl.glBegin(bgl.GL_LINE_LOOP)
    for x, y in self.mouse_path:
        bgl.glVertex2f(x, y)
    bgl.glEnd()


    bgl.glDisable(bgl.GL_BLEND)
    bgl.glDisable(bgl.GL_LINE_SMOOTH)
    #bgl.glDisable(bgl.GL_POLYGON_SMOOTH)   



class ModalDrawOperator(bpy.types.Operator):
    bl_idname = "object.modal_operator"
    bl_label = "Simple Modal Operator"

    def modal(self, context, event):
        context.area.tag_redraw()

        if event.type == 'LEFTMOUSE':
            self.mouse_path.append(
            (event.mouse_region_x, event.mouse_region_y))

        if event.type in ['RIGHTMOUSE','ESC']:
            context.space_data.draw_handler_remove(self._handle, 'WINDOW')
            return {'FINISHED'}

        return {'RUNNING_MODAL'}


    def invoke(self, context, event):
        self.mouse_path = []

        args = (self, context)
        self._handle = context.space_data.draw_handler_add(
        draw_callback_px, args, 'WINDOW', 'POST_PIXEL')

        context.window_manager.modal_handler_add(self)
        return {'RUNNING_MODAL'}


bpy.utils.register_class(ModalDrawOperator)
bpy.ops.object.modal_operator('INVOKE_DEFAULT')

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.