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