RenderEngine(bpy_struct)

Simple Render Engine


import bpy
import bgl


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"
    bl_label = "Custom"
    bl_use_preview = True

    # Init is called whenever a new render engine instance is created. Multiple
    # instances may exist at the same time, for example for a viewport and final
    # render.
    def __init__(self):
        self.scene_data = None
        self.draw_data = None

    # When the render engine instance is destroy, this is called. Clean up any
    # render engine data here, for example stopping running render threads.
    def __del__(self):
        pass

    # This is the method called by Blender for both final renders (F12) and
    # small preview for materials, world and lights.
    def render(self, depsgraph):
        scene = depsgraph.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)

        # Fill the render result with a flat color. The framebuffer is
        # defined as a list of pixels, each pixel itself being a list of
        # R,G,B,A values.
        if self.is_preview:
            color = [0.1, 0.2, 0.1, 1.0]
        else:
            color = [0.2, 0.1, 0.1, 1.0]

        pixel_count = self.size_x * self.size_y
        rect = [color] * 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].passes["Combined"]
        layer.rect = rect
        self.end_result(result)

    # For viewport renders, this method gets called once at the start and
    # whenever the scene or 3D viewport changes. This method is where data
    # should be read from Blender in the same thread. Typically a render
    # thread will be started to do the work while keeping Blender responsive.
    def view_update(self, context, depsgraph):
        region = context.region
        view3d = context.space_data
        scene = depsgraph.scene

        # Get viewport dimensions
        dimensions = region.width, region.height

        if not self.scene_data:
            # First time initialization
            self.scene_data = []
            first_time = True

            # Loop over all datablocks used in the scene.
            for datablock in depsgraph.ids:
                pass
        else:
            first_time = False

            # Test which datablocks changed
            for update in depsgraph.updates:
                print("Datablock updated: ", update.id.name)

            # Test if any material was added, removed or changed.
            if depsgraph.id_type_updated('MATERIAL'):
                print("Materials updated")

        # Loop over all object instances in the scene.
        if first_time or depsgraph.id_type_updated('OBJECT'):
            for instance in depsgraph.object_instances:
                pass

    # For viewport renders, this method is called whenever Blender redraws
    # the 3D viewport. The renderer is expected to quickly draw the render
    # with OpenGL, and not perform other expensive work.
    # Blender will draw overlays for selection and editing on top of the
    # rendered image automatically.
    def view_draw(self, context, depsgraph):
        region = context.region
        scene = depsgraph.scene

        # Get viewport dimensions
        dimensions = region.width, region.height

        # Bind shader that converts from scene linear to display space,
        bgl.glEnable(bgl.GL_BLEND)
        bgl.glBlendFunc(bgl.GL_ONE, bgl.GL_ONE_MINUS_SRC_ALPHA)
        self.bind_display_space_shader(scene)

        if not self.draw_data or self.draw_data.dimensions != dimensions:
            self.draw_data = CustomDrawData(dimensions)

        self.draw_data.draw()

        self.unbind_display_space_shader()
        bgl.glDisable(bgl.GL_BLEND)


class CustomDrawData:
    def __init__(self, dimensions):
        # Generate dummy float image buffer
        self.dimensions = dimensions
        width, height = dimensions

        pixels = [0.1, 0.2, 0.1, 1.0] * width * height
        pixels = bgl.Buffer(bgl.GL_FLOAT, width * height * 4, pixels)

        # Generate texture
        self.texture = bgl.Buffer(bgl.GL_INT, 1)
        bgl.glGenTextures(1, self.texture)
        bgl.glActiveTexture(bgl.GL_TEXTURE0)
        bgl.glBindTexture(bgl.GL_TEXTURE_2D, self.texture[0])
        bgl.glTexImage2D(bgl.GL_TEXTURE_2D, 0, bgl.GL_RGBA16F, width, height, 0, bgl.GL_RGBA, bgl.GL_FLOAT, pixels)
        bgl.glTexParameteri(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_MIN_FILTER, bgl.GL_LINEAR)
        bgl.glTexParameteri(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_MAG_FILTER, bgl.GL_LINEAR)
        bgl.glBindTexture(bgl.GL_TEXTURE_2D, 0)

        # Bind shader that converts from scene linear to display space,
        # use the scene's color management settings.
        shader_program = bgl.Buffer(bgl.GL_INT, 1)
        bgl.glGetIntegerv(bgl.GL_CURRENT_PROGRAM, shader_program)

        # Generate vertex array
        self.vertex_array = bgl.Buffer(bgl.GL_INT, 1)
        bgl.glGenVertexArrays(1, self.vertex_array)
        bgl.glBindVertexArray(self.vertex_array[0])

        texturecoord_location = bgl.glGetAttribLocation(shader_program[0], "texCoord")
        position_location = bgl.glGetAttribLocation(shader_program[0], "pos")

        bgl.glEnableVertexAttribArray(texturecoord_location)
        bgl.glEnableVertexAttribArray(position_location)

        # Generate geometry buffers for drawing textured quad
        position = [0.0, 0.0, width, 0.0, width, height, 0.0, height]
        position = bgl.Buffer(bgl.GL_FLOAT, len(position), position)
        texcoord = [0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0]
        texcoord = bgl.Buffer(bgl.GL_FLOAT, len(texcoord), texcoord)

        self.vertex_buffer = bgl.Buffer(bgl.GL_INT, 2)

        bgl.glGenBuffers(2, self.vertex_buffer)
        bgl.glBindBuffer(bgl.GL_ARRAY_BUFFER, self.vertex_buffer[0])
        bgl.glBufferData(bgl.GL_ARRAY_BUFFER, 32, position, bgl.GL_STATIC_DRAW)
        bgl.glVertexAttribPointer(position_location, 2, bgl.GL_FLOAT, bgl.GL_FALSE, 0, None)

        bgl.glBindBuffer(bgl.GL_ARRAY_BUFFER, self.vertex_buffer[1])
        bgl.glBufferData(bgl.GL_ARRAY_BUFFER, 32, texcoord, bgl.GL_STATIC_DRAW)
        bgl.glVertexAttribPointer(texturecoord_location, 2, bgl.GL_FLOAT, bgl.GL_FALSE, 0, None)

        bgl.glBindBuffer(bgl.GL_ARRAY_BUFFER, 0)
        bgl.glBindVertexArray(0)

    def __del__(self):
        bgl.glDeleteBuffers(2, self.vertex_buffer)
        bgl.glDeleteVertexArrays(1, self.vertex_array)
        bgl.glBindTexture(bgl.GL_TEXTURE_2D, 0)
        bgl.glDeleteTextures(1, self.texture)

    def draw(self):
        bgl.glActiveTexture(bgl.GL_TEXTURE0)
        bgl.glBindTexture(bgl.GL_TEXTURE_2D, self.texture[0])
        bgl.glBindVertexArray(self.vertex_array[0])
        bgl.glDrawArrays(bgl.GL_TRIANGLE_FAN, 0, 4)
        bgl.glBindVertexArray(0)
        bgl.glBindTexture(bgl.GL_TEXTURE_2D, 0)


# RenderEngines also need to tell UI Panels that they are compatible with.
# We recommend to enable all panels marked as BLENDER_RENDER, and then
# exclude any panels that are replaced by custom panels registered by the
# render engine, or that are not supported.
def get_panels():
    exclude_panels = {
        'VIEWLAYER_PT_filter',
        'VIEWLAYER_PT_layer_passes',
    }

    panels = []
    for panel in bpy.types.Panel.__subclasses__():
        if hasattr(panel, 'COMPAT_ENGINES') and 'BLENDER_RENDER' in panel.COMPAT_ENGINES:
            if panel.__name__ not in exclude_panels:
                panels.append(panel)

    return panels


def register():
    # Register the RenderEngine
    bpy.utils.register_class(CustomRenderEngine)

    for panel in get_panels():
        panel.COMPAT_ENGINES.add('CUSTOM')


def unregister():
    bpy.utils.unregister_class(CustomRenderEngine)

    for panel in get_panels():
        if 'CUSTOM' in panel.COMPAT_ENGINES:
            panel.COMPAT_ENGINES.remove('CUSTOM')


if __name__ == "__main__":
    register()

base class — bpy_struct

class bpy.types.RenderEngine(bpy_struct)

Render engine

bl_idname
Type

string, default “”, (never None)

bl_label
Type

string, default “”, (never None)

bl_use_eevee_viewport

Uses Eevee for viewport shading in LookDev shading mode

Type

boolean, default False

bl_use_postprocess

Apply compositing on render results

Type

boolean, default False

bl_use_preview

Render engine supports being used for rendering previews of materials, lights and worlds

Type

boolean, default False

bl_use_save_buffers

Support render to an on disk buffer during rendering

Type

boolean, default False

bl_use_shading_nodes_custom

Don’t expose Cycles and Eevee shading nodes in the node editor user interface, so own nodes can be used instead

Type

boolean, default True

bl_use_spherical_stereo

Support spherical stereo camera models

Type

boolean, default False

bl_use_stereo_viewport

Support rendering stereo 3D viewport

Type

boolean, default False

camera_override
Type

Object, (readonly)

is_animation
Type

boolean, default False

is_preview
Type

boolean, default False

layer_override
Type

boolean array of 20 items, default (False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False)

render
Type

RenderSettings, (readonly)

resolution_x
Type

int in [-inf, inf], default 0, (readonly)

resolution_y
Type

int in [-inf, inf], default 0, (readonly)

tile_x
Type

int in [0, inf], default 0

tile_y
Type

int in [0, inf], default 0

use_highlight_tiles
Type

boolean, default False

update(data=None, depsgraph=None)

Export scene data for render

render(depsgraph)

Render scene into an image

bake(depsgraph, object, pass_type, pass_filter, object_id, pixel_array, num_pixels, depth, result)

Bake passes

Parameters
  • pass_type (enum in ['COMBINED', 'AO', 'SHADOW', 'NORMAL', 'UV', 'ROUGHNESS', 'EMIT', 'ENVIRONMENT', 'DIFFUSE', 'GLOSSY', 'TRANSMISSION']) – Pass, Pass to bake

  • pass_filter (int in [0, inf]) – Pass Filter, Filter to combined, diffuse, glossy and transmission passes

  • object_id (int in [0, inf]) – Object Id, Id of the current object being baked in relation to the others

  • num_pixels (int in [0, inf]) – Number of Pixels, Size of the baking batch

  • depth (int in [0, inf]) – Pixels depth, Number of channels

view_update(context, depsgraph)

Update on data changes for viewport render

view_draw(context, depsgraph)

Draw viewport render

update_script_node(node=None)

Compile shader script node

update_render_passes(scene=None, renderlayer=None)

Update the render passes that will be generated

tag_redraw()

Request redraw for viewport rendering

tag_update()

Request update call for viewport rendering

begin_result(x, y, w, h, layer="", view="")

Create render result to write linear floating point render layers and passes

Parameters
  • x (int in [0, inf]) – X

  • y (int in [0, inf]) – Y

  • w (int in [0, inf]) – Width

  • h (int in [0, inf]) – Height

  • layer (string, (optional, never None)) – Layer, Single layer to get render result for

  • view (string, (optional, never None)) – View, Single view to get render result for

Returns

Result

Return type

RenderResult

update_result(result)

Signal that pixels have been updated and can be redrawn in the user interface

Parameters

result (RenderResult) – Result

end_result(result, cancel=False, highlight=False, do_merge_results=False)

All pixels in the render result have been set and are final

Parameters
  • result (RenderResult) – Result

  • cancel (boolean, (optional)) – Cancel, Don’t mark tile as done, don’t merge results unless forced

  • highlight (boolean, (optional)) – Highlight, Don’t mark tile as done yet

  • do_merge_results (boolean, (optional)) – Merge Results, Merge results even if cancel=true

add_pass(name, channels, chan_id, layer="")

Add a pass to the render layer

Parameters
  • name (string, (never None)) – Name, Name of the Pass, without view or channel tag

  • channels (int in [0, inf]) – Channels

  • chan_id (string, (never None)) – Channel IDs, Channel names, one character per channel

  • layer (string, (optional, never None)) – Layer, Single layer to add render pass to

get_result()

Get final result for non-pixel operations

Returns

Result

Return type

RenderResult

test_break()

Test if the render operation should been canceled, this is a fast call that should be used regularly for responsiveness

Returns

Break

Return type

boolean

active_view_get()

active_view_get

Returns

View, Single view active

Return type

string, (never None)

active_view_set(view)

active_view_set

Parameters

view (string, (never None)) – View, Single view to set as active

camera_shift_x(camera, use_spherical_stereo=False)

camera_shift_x

Parameters

use_spherical_stereo (boolean, (optional)) – Spherical Stereo

Returns

Shift X

Return type

float in [0, inf]

camera_model_matrix(camera, use_spherical_stereo=False)

camera_model_matrix

Parameters

use_spherical_stereo (boolean, (optional)) – Spherical Stereo

Returns

Model Matrix, Normalized camera model matrix

Return type

float multi-dimensional array of 4 * 4 items in [-inf, inf]

use_spherical_stereo(camera)

use_spherical_stereo

Returns

Spherical Stereo

Return type

boolean

update_stats(stats, info)

Update and signal to redraw render status text

Parameters
  • stats (string, (never None)) – Stats

  • info (string, (never None)) – Info

frame_set(frame, subframe)

Evaluate scene at a different frame (for motion blur)

Parameters
  • frame (int in [-inf, inf]) – Frame

  • subframe (float in [0, 1]) – Subframe

update_progress(progress)

Update progress percentage of render

Parameters

progress (float in [0, 1]) – Percentage of render that’s done

update_memory_stats(memory_used=0.0, memory_peak=0.0)

Update memory usage statistics

Parameters
  • memory_used (float in [0, inf], (optional)) – Current memory usage in megabytes

  • memory_peak (float in [0, inf], (optional)) – Peak memory usage in megabytes

report(type, message)

Report info, warning or error messages

Parameters
  • type (enum set in {'DEBUG', 'INFO', 'OPERATOR', 'PROPERTY', 'WARNING', 'ERROR', 'ERROR_INVALID_INPUT', 'ERROR_INVALID_CONTEXT', 'ERROR_OUT_OF_MEMORY'}) – Type

  • message (string, (never None)) – Report Message

error_set(message)

Set error message displaying after the render is finished

Parameters

message (string, (never None)) – Report Message

bind_display_space_shader(scene)

Bind GLSL fragment shader that converts linear colors to display space colors using scene color management settings

unbind_display_space_shader()

Unbind GLSL display space shader, must always be called after binding the shader

support_display_space_shader(scene)

Test if GLSL display space shader is supported for the combination of graphics card and scene settings

Returns

Supported

Return type

boolean

get_preview_pixel_size(scene)

Free Blender side memory of render engine

Returns

Pixel Size

Return type

int in [1, 8]

free_blender_memory()

free_blender_memory

register_pass(scene, view_layer, name, channels, chanid, type)

Register a render pass that will be part of the render with the current settings

Parameters
  • name (string, (never None)) – Name

  • channels (int in [1, 8]) – Channels

  • chanid (string, (never None)) – Channel IDs

  • type (enum in ['VALUE', 'VECTOR', 'COLOR']) – Type

classmethod bl_rna_get_subclass(id, default=None)
Parameters

id (string) – The RNA type identifier.

Returns

The RNA type or default when not found.

Return type

bpy.types.Struct subclass

classmethod bl_rna_get_subclass_py(id, default=None)
Parameters

id (string) – The RNA type identifier.

Returns

The class or default when not found.

Return type

type

Inherited Properties

Inherited Functions