Custom RenderEngine for Viewport

Hi I’m new to Blender plugin development, and I’m trying to write a custom renderer for blender’s viewport. I found this example http://www.blender.org/documentation/blender_python_api_2_68a_release/bpy.types.RenderEngine.html in the docs. However it doesnt show how should I use the OpenGL to implement the method view_draw/view_update. Can anyone give a hand just posting an hello world show how can I put OpenGL/Custom code for rendering in this area??

Thanks

What i calculate there is just wrong, please don’t mind :wink:

import bpy
import bgl
from mathutils import Vector, Matrix

class CustomRenderEngine(bpy.types.RenderEngine):
    # These three members are used by blender to set up the
    # RenderEngine; define its internal name, visible name and capabilities.
    bl_idname = 'custom_renderer'
    bl_label = 'Flat Color Renderer'
    bl_use_preview = True

    # This is the only method called by blender, in this example
    # we use it to detect preview rendering and call the implementation
    # in another method.
    def render(self, scene):
        scale = scene.render.resolution_percentage / 100.0
        self.size_x = int(scene.render.resolution_x * scale)
        self.size_y = int(scene.render.resolution_y * scale)

        if scene.name == 'preview':
            self.render_preview(scene)
        else:
            self.render_scene(scene)

    # In this example, we fill the preview renders with a flat green color.
    def render_preview(self, scene):
        pixel_count = self.size_x * self.size_y

        # The framebuffer is defined as a list of pixels, each pixel
        # itself being a list of R,G,B,A values
        green_rect = [[0.0, 1.0, 0.0, 1.0]] * pixel_count

        # Here we write the pixel values to the RenderResult
        result = self.begin_result(0, 0, self.size_x, self.size_y)
        layer = result.layers[0]
        layer.rect = green_rect
        self.end_result(result)

    # In this example, we fill the full renders with a flat blue color.
    def render_scene(self, scene):
        pixel_count = self.size_x * self.size_y

        # The framebuffer is defined as a list of pixels, each pixel
        # itself being a list of R,G,B,A values
        blue_rect = [[0.0, 0.0, 1.0, 1.0]] * pixel_count

        # Here we write the pixel values to the RenderResult
        result = self.begin_result(0, 0, self.size_x, self.size_y)
        layer = result.layers[0]
        layer.rect = blue_rect
        self.end_result(result)
        
    def view_update(self, context):
        draw_callback_px(self, context)
        
        
    def view_draw(self, context):
        draw_callback_px(self, context)

def draw_callback_px(self, context):

    ob = context.object
    if ob is None or ob.type not in ('MESH', 'CURVE', 'SURFACE', 'META', 'FONT'):
        # Type that doesn't support .bound_box
        print("no ob")
        return
    
    
    #mat = context.screen.areas[2].spaces[0].region_3d.view_matrix * Matrix.Scale(20, 4) #* Matrix.Translation(-context.screen.areas[2].spaces[0].region_3d.view_location) #ob.matrix_world
    #mat = context.screen.areas[2].spaces[0].region_3d.perspective_matrix * Matrix.Scale(20, 4)
    r3d = context.space_data.region_3d
    
    mat = r3d.perspective_matrix  * Matrix.Scale(r3d.view_distance, 4) #* Matrix.Translation(r3d.view_location)
    
    # 50% alpha, 2 pixel width line
    bgl.glEnable(bgl.GL_BLEND)
    bgl.glColor4f(1.0, 0.0, 0.0, 0.5)
    bgl.glLineWidth(2)
    
    bbox = [mat * Vector(b) for b in ob.bound_box]

    bgl.glBegin(bgl.GL_LINE_STRIP)
    bgl.glVertex3f(*bbox[0])
    bgl.glVertex3f(*bbox[1])
    bgl.glVertex3f(*bbox[2])
    bgl.glVertex3f(*bbox[3])
    bgl.glVertex3f(*bbox[0])
    bgl.glVertex3f(*bbox[4])
    bgl.glVertex3f(*bbox[5])
    bgl.glVertex3f(*bbox[6])
    bgl.glVertex3f(*bbox[7])
    bgl.glVertex3f(*bbox[4])
    bgl.glEnd()
    
    bgl.glBegin(bgl.GL_LINES)
    bgl.glVertex3f(*bbox[1])
    bgl.glVertex3f(*bbox[5])
    bgl.glVertex3f(*bbox[2])
    bgl.glVertex3f(*bbox[6])
    bgl.glVertex3f(*bbox[3])
    bgl.glVertex3f(*bbox[7])
    bgl.glEnd()
    
    # restore opengl defaults
    bgl.glLineWidth(1)
    bgl.glDisable(bgl.GL_BLEND)
    bgl.glColor4f(0.0, 0.0, 0.0, 1.0)
    
# Register the RenderEngine
bpy.utils.register_class(CustomRenderEngine)

# RenderEngines also need to tell UI Panels that they are compatible
# Otherwise most of the UI will be empty when the engine is selected.
# In this example, we need to see the main render image button and
# the material preview panel.
from bl_ui import properties_render
properties_render.RENDER_PT_render.COMPAT_ENGINES.add('custom_renderer')
del properties_render

from bl_ui import properties_material
properties_material.MATERIAL_PT_preview.COMPAT_ENGINES.add('custom_renderer')
del properties_material

Thanks!! :wink: It worked. Do you know if I can find more material related to this, besides the bpy.types.RenderEngine doc page (it is too simple =P)?

Best source is probably a mature renderengine addon, but most of them seem to render externally and not use the live preview?

Here’s POVray:
https://svn.blender.org/svnroot/bf-extensions/trunk/py/scripts/addons/render_povray/render.py

Yeap thats the problem, I didnt find any of them using the live preview! However, I think what I’m planning to do can do the same thing, and then I only use the opengl to show the texture with the result, so it keeps interactive :wink:

Thanks for the help!