Created
July 13, 2023 14:58
-
-
Save blender8r/74655fabb002c1e9fbf973174e6372c4 to your computer and use it in GitHub Desktop.
Blender script to add depth of field effect to grease pencil objects
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import bpy | |
| from mathutils import Vector | |
| def duplicate(obj, data=True, actions=True, collection=None): | |
| obj_copy = obj.copy() | |
| if data: | |
| obj_copy.data = obj_copy.data.copy() | |
| if actions and obj_copy.animation_data.action: | |
| obj_copy.animation_data.action = obj_copy.animation_data.action.copy() | |
| bpy.context.collection.objects.link(obj_copy) | |
| return obj_copy | |
| def get_distance(pos1, pos2): | |
| vp1 = Vector(pos1) | |
| vp2 = Vector(pos2) | |
| return (vp2 - vp1).length | |
| def get_stroke_position(gp, stroke): | |
| cx, cy, cz = 0.0, 0.0, 0.0 | |
| num_pts = 0 | |
| for p in stroke.points: | |
| p_local = p.co | |
| p_global = gp.matrix_world @ p_local | |
| cx += p_global[0] | |
| cy += p_global[1] | |
| cz += p_global[2] | |
| num_pts += 1 | |
| return (cx/num_pts, cy/num_pts, cz/num_pts) | |
| def distance_to_camera(cam_pos, gp, stroke): | |
| stroke_pos = get_stroke_position(gp, stroke) | |
| distance_to_cam = get_distance(cam_pos, stroke_pos) | |
| return distance_to_cam | |
| def center_origin(gp): | |
| cx, cy, cz = 0.0, 0.0, 0.0 | |
| num_strokes = 0 | |
| for layer in gp.data.layers: | |
| for frame in layer.frames: | |
| for stroke in frame.strokes: | |
| position = get_stroke_position(gp, stroke) | |
| cx += position[0] | |
| cy += position[1] | |
| cz += position[2] | |
| num_strokes += 1 | |
| new_origin = (cx/num_strokes, cy/num_strokes, cz/num_strokes) | |
| gp_origin = gp.matrix_world.translation | |
| offset = (gp_origin[0]-new_origin[0], gp_origin[1]-new_origin[1], gp_origin[2]-new_origin[2]) | |
| for layer in gp.data.layers: | |
| for frame in layer.frames: | |
| for stroke in frame.strokes: | |
| for p in stroke.points: | |
| p.co = (p.co[0]+offset[0], p.co[1]+offset[1], p.co[2]+offset[2]) | |
| gp.location = (gp.location[0]-offset[0], gp.location[1]-offset[1], gp.location[2]-offset[2]) | |
| min_depth = 0 | |
| max_depth = 0 | |
| step = 2 | |
| grease_pencils = [] | |
| cameras = [] | |
| error = None | |
| sel_objs = bpy.context.selected_objects | |
| if sel_objs: | |
| for sel in sel_objs: | |
| if sel.type == 'GPENCIL': | |
| grease_pencils.append(sel) | |
| elif sel.type == 'CAMERA': | |
| cameras.append(sel) | |
| if grease_pencils and cameras: | |
| if len(cameras) > 1: | |
| error = "More than one camera selected!" | |
| else: | |
| camera = cameras[0] | |
| else: | |
| error = "You must select at least one grease pencil and one camera!" | |
| if error: | |
| print(error) | |
| else: | |
| for gp in grease_pencils: | |
| stroke_distances = [] | |
| for layer in gp.data.layers: | |
| for frame in layer.frames: | |
| cam_pos = camera.matrix_world.translation | |
| for stroke in frame.strokes: | |
| stroke_distances.append(distance_to_camera(cam_pos, gp, stroke)) | |
| min_depth = min(stroke_distances) | |
| max_depth = max(stroke_distances) | |
| i = min_depth | |
| while i <= max_depth: | |
| gp_dof = duplicate(gp) | |
| for layer in gp_dof.data.layers: | |
| for frame in layer.frames: | |
| for stroke in frame.strokes: | |
| cam_pos = camera.matrix_world.translation | |
| dist = distance_to_camera(cam_pos, gp, stroke) | |
| if dist < i or dist > i + step: | |
| frame.strokes.remove(stroke) | |
| num_strokes = 0 | |
| for layer in gp_dof.data.layers: | |
| for frame in layer.frames: | |
| num_strokes += len(frame.strokes) | |
| if num_strokes == 0: | |
| bpy.data.objects.remove(gp_dof) | |
| else: | |
| shader_fx = gp_dof.shader_effects.new('blur', 'FX_BLUR') | |
| shader_fx.use_dof_mode = True | |
| shader_fx.samples = 16 | |
| center_origin(gp_dof) | |
| i += step | |
| gp.hide_viewport = True | |
| gp.hide_render = True | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment