How do I get object names to appear in the render?
For the labels to be visible in the render they must be created as objects within the scene. The following script will process each object in turn and automatically create a Text object set to the object's name and position the Text in front of the camera so that it is in line with the object (1.0 blender unit infront of the camera) :

# Script to automatically generate labels for all objects in the scene and position them in the camera view
# Generated labels are prefixed with '_generated.' and replaced each time the script is run.
# Note that any objects with name that happens to start with '_generated.' will be automatically deleted!
#
# This script will automatically create a material named '_generated.Label' and assign it to all generated labels.
# The generated material can be modified to affect the appearance of the labels.

import bpy
from bpy_extras.object_utils import world_to_camera_view

scn = bpy.context.scene
cam = scn.camera

# Pickup the label material if it exists
mat = bpy.data.materials.get("_generated.Label")

if mat is None:
    # Material doesn't exist, create it
    mat = bpy.data.materials.new(name="_generated.Label")

# Get each object in turn
for obj in scn.objects:
    if obj.name.startswith('_generated.'):
        # Delete the old label
        scn.objects.unlink(obj)
        bpy.data.objects.remove(obj)
    else:
        # Create a new label
        bpy.ops.object.text_add()
        tobj = bpy.context.object

        # Set the name of the label to include the prefix so we can identify them and set the text
        tobj.name = '_generated.'+obj.name
        tobj.data.body = obj.name

        # Position the label between the camera and the object
        diffloc = obj.location - cam.location
        dist = (diffloc[0]**2 + diffloc[1]**2 + diffloc[2]**2)**0.5
        if dist == 0:
            tobj.location = cam.location
        else:
            tobj.location = cam.location + (diffloc / dist * 1.0)  #1.0 blender unit from the camera

        # Set the rotation the same as the camera and scale it appropriate to the distance
        tobj.rotation_euler = cam.rotation_euler
        tobj.scale = (0.03,0.03,0.03)

        # Assign material to object
        if tobj.data.materials:
            # assign to 1st material slot
            tobj.data.materials[0] = mat
        else:
            # no slots
            tobj.data.materials.append(mat)        


Open a Text Editor window and click 'New' and name it 'objectnames.py'. Paste the above text into the window and click Run Script to run it.

The script examines each object in turn and calculates a position in line with the object where a label needs to be positioned for it to overlay the object. A new Text object is created at that location, orientated to face the camera, and assigned a material.



Once the script is run, switching to Camera view should show the labels positioned over each object in the scene. Changing the generated material '_generated.Label' will affect the appearance of all labels in the render.

The line :

tobj.location = cam.location + (diffloc / dist * 1.0)


affects the location of the labels - with the '1.0' indicating how far from the camera the labels should be positioned - amend it and re-run the script to position them closer or further from the camera.

Similarly, the line setting 'tobj.scale = (....)' sets the scale of the labels - again, amend that line to change the scale if desired (larger values give larger labels).

Amend the '_generated.Label' material to affect how the labels are rendered. For example, to give them an emission colour without the emission affecting the rest of the scene you may have something like the following :



This can produce the following result :



For animated scenes you will need to run the script for each frame of the animation to reposition the labels. This can be achieved via a "handler" which can be registered to execute each time the frame changes. This can be achieved with the following code :

# Script to automatically generate labels for all objects in the scene and position them in the camera view
# Generated labels are prefixed with '_generated.' and replaced each time the script is run.
# Note that any objects with name that happens to start with '_generated.' will be automatically deleted!
#
# This script will automatically create a material named '_generated.Label' and assign it to all generated labels.
# The generated material can be modified to affect the appearance of the labels.
#
# Scene Custom Property '_generated_label_scale' can be set to a numeric to set the scale of the labels.
# Create an object group named 'Labels' and place any objects within it to only render labels for those specific objects.

import bpy

def handler_object_labels(scn):

    cam = scn.camera

    labelscale = scn["_generated_label_scale"]

    # Pickup the label material if it exists
    mat = bpy.data.materials.get("_generated.Label")

    if mat is None:
        # Material doesn't exist, create it
        mat = bpy.data.materials.new(name="_generated.Label")

    # Get each object in turn
    for obj in scn.objects:
        if obj.name.startswith('_generated.'):
            # Delete the old label
            curve = obj.data
            scn.objects.unlink(obj)
            bpy.data.objects.remove(obj)
            bpy.data.curves.remove(curve)
        else:
            # Check if group 'Labels' exists and if object within that group
            if bpy.data.groups.get("Labels") != None:
                if (bpy.data.groups["Labels"].objects.get(obj.name) == None):
                    continue

            # Create a new label
            curve = bpy.data.curves.new(type="FONT",name="_generated."+obj.name)
            tobj = bpy.data.objects.new("_generated."+obj.name,curve)
            bpy.context.scene.objects.link(tobj)

            # Set the name of the label to include the prefix so we can identify them and set the text
            tobj.name = '_generated.'+obj.name
            tobj.data.body = obj.name

            camloc = cam.matrix_world.to_translation()

            # Position the label between the camera and the object
            diffloc = obj.location - camloc
            dist = (diffloc[0]**2 + diffloc[1]**2 + diffloc[2]**2)**0.5
            if dist == 0:
                tobj.location = camloc
            else:
                tobj.location = camloc + (diffloc / dist * 1.0)  #1.0 blender unit from the camera

            # Set the rotation the same as the camera and scale it appropriate to the distance
            tobj.rotation_euler = cam.matrix_world.to_euler()
            tobj.scale = (labelscale, labelscale, labelscale)

            # Assign material to object
            if tobj.data.materials:
                # assign to 1st material slot
                tobj.data.materials[0] = mat
            else:
                # no slots
                tobj.data.materials.append(mat)

    bpy.context.scene.update()

if not '_generated_label_scale' in bpy.context.scene.keys():
    bpy.context.scene["_generated_label_scale"] = 0.06

if handler_object_labels in bpy.app.handlers.frame_change_post:
    bpy.app.handlers.remove(handler_object_labels)
bpy.app.handlers.frame_change_post.append(handler_object_labels)


Note that this script uses a Scene Custom Property (_generated_label_scale) to control the scale of the labels (defaults to 0.06). By default, labels will be created for all objects in the scene. However, if a group named 'Labels' is found then only those objects within the group are given labels (so select all the objects you want to have labels, select Object/Group/Create New Group from the menu, then on the Objects propert panel rename the group to 'Labels').

Note that the labels are only refreshed on change of frame - so if you move objects or the camera you'll need to swap frame before the labels re-arrange.

This can produce the following result :



Blend file included