blender-grease-pencil

Create 2D art and animation in Blender using Grease Pencil and Python. Use when the user wants to draw strokes programmatically, create 2D animations, build Grease Pencil objects from code, manage GP layers and frames, apply GP modifiers, set up drawing guides, or script any Grease Pencil workflow in Blender.

26 stars

Best use case

blender-grease-pencil is best used when you need a repeatable AI agent workflow instead of a one-off prompt.

Create 2D art and animation in Blender using Grease Pencil and Python. Use when the user wants to draw strokes programmatically, create 2D animations, build Grease Pencil objects from code, manage GP layers and frames, apply GP modifiers, set up drawing guides, or script any Grease Pencil workflow in Blender.

Teams using blender-grease-pencil should expect a more consistent output, faster repeated execution, less prompt rewriting.

When to use this skill

  • You want a reusable workflow that can be run more than once with consistent structure.

When not to use this skill

  • You only need a quick one-off answer and do not need a reusable workflow.
  • You cannot install or maintain the underlying files, dependencies, or repository context.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/blender-grease-pencil/SKILL.md --create-dirs "https://raw.githubusercontent.com/TerminalSkills/skills/main/skills/blender-grease-pencil/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/blender-grease-pencil/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How blender-grease-pencil Compares

Feature / Agentblender-grease-pencilStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

Create 2D art and animation in Blender using Grease Pencil and Python. Use when the user wants to draw strokes programmatically, create 2D animations, build Grease Pencil objects from code, manage GP layers and frames, apply GP modifiers, set up drawing guides, or script any Grease Pencil workflow in Blender.

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

Related Guides

SKILL.md Source

# Blender Grease Pencil

## Overview

Create 2D drawings and animations in Blender's 3D space using the Grease Pencil system and Python. Build strokes from point data, manage layers and frames, apply GP-specific modifiers, and animate 2D content — all scriptable from the terminal.

## Instructions

### 1. Create a Grease Pencil object

```python
import bpy

# Create a new Grease Pencil data block and object
gp_data = bpy.data.grease_pencils.new("MyDrawing")
gp_obj = bpy.data.objects.new("MyDrawing", gp_data)
bpy.context.collection.objects.link(gp_obj)

# Or use the operator
bpy.ops.object.gpencil_add(type='EMPTY')  # EMPTY, STROKE, MONKEY, SCENE, COLLECTION
gp_obj = bpy.context.active_object
```

Types for `gpencil_add`: `EMPTY` (blank), `STROKE` (single stroke), `MONKEY` (Suzanne in 2D), `SCENE` (draw over scene), `COLLECTION` (from collection).

### 2. Add layers and frames

```python
import bpy

gp_data = bpy.context.active_object.data

# Create a layer
layer = gp_data.layers.new("Outlines", set_active=True)
layer.info = "Outlines"
layer.blend_mode = 'REGULAR'  # REGULAR, OVERLAY, ADD, SUBTRACT, MULTIPLY
layer.opacity = 1.0
layer.use_lights = False

# Create a keyframe on the layer at a specific frame
frame = layer.frames.new(frame_number=1)

# Additional layers for organization
color_layer = gp_data.layers.new("Colors", set_active=False)
color_frame = color_layer.frames.new(frame_number=1)
```

### 3. Draw strokes programmatically

```python
import bpy

gp_obj = bpy.context.active_object
gp_data = gp_obj.data
layer = gp_data.layers.active
frame = layer.frames[0]  # or layer.active_frame

# Create a stroke
stroke = frame.strokes.new()
stroke.display_mode = '3DSPACE'  # 3DSPACE, 2DSPACE, 2DIMAGE, SCREEN
stroke.line_width = 10

# Add points to the stroke
num_points = 5
stroke.points.add(num_points)

coords = [(0, 0, 0), (1, 0.5, 0), (2, 1, 0), (3, 0.5, 0), (4, 0, 0)]
for i, (x, y, z) in enumerate(coords):
    stroke.points[i].co = (x, y, z)
    stroke.points[i].pressure = 1.0      # pen pressure (0.0 - 1.0)
    stroke.points[i].strength = 1.0      # color strength (0.0 - 1.0)

# Assign material index to stroke
stroke.material_index = 0
```

### 4. Create GP materials

```python
import bpy

gp_obj = bpy.context.active_object

# Solid fill material
mat_solid = bpy.data.materials.new("GP_Solid")
bpy.data.materials.create_gpencil_data(mat_solid)
mat_solid.grease_pencil.color = (0.1, 0.1, 0.1, 1.0)       # stroke color
mat_solid.grease_pencil.fill_color = (0.8, 0.2, 0.2, 1.0)  # fill color
mat_solid.grease_pencil.show_fill = True
mat_solid.grease_pencil.show_stroke = True
gp_obj.data.materials.append(mat_solid)

# Line-only material
mat_line = bpy.data.materials.new("GP_Line")
bpy.data.materials.create_gpencil_data(mat_line)
mat_line.grease_pencil.color = (0.0, 0.0, 0.0, 1.0)
mat_line.grease_pencil.show_fill = False
mat_line.grease_pencil.show_stroke = True
gp_obj.data.materials.append(mat_line)
```

### 5. Apply Grease Pencil modifiers

```python
import bpy

gp_obj = bpy.context.active_object

# Thickness modifier
thick = gp_obj.grease_pencil_modifiers.new("Thickness", 'GP_THICK')
thick.thickness_factor = 1.5

# Smooth modifier
smooth = gp_obj.grease_pencil_modifiers.new("Smooth", 'GP_SMOOTH')
smooth.factor = 0.5
smooth.step = 3

# Tint modifier (color shift)
tint = gp_obj.grease_pencil_modifiers.new("Tint", 'GP_TINT')
tint.color = (0.2, 0.5, 1.0)
tint.factor = 0.3

# Noise modifier (hand-drawn look)
noise = gp_obj.grease_pencil_modifiers.new("Noise", 'GP_NOISE')
noise.factor = 0.5

# Subdivide modifier (smoother curves)
subdiv = gp_obj.grease_pencil_modifiers.new("Subdivide", 'GP_SUBDIV')
subdiv.level = 2

# Build modifier (animated reveal)
build = gp_obj.grease_pencil_modifiers.new("Build", 'GP_BUILD')
build.mode = 'SEQUENTIAL'  # SEQUENTIAL, CONCURRENT, ADDITIVE
build.start_frame = 1
build.length = 50

# Array modifier (repeat strokes)
array = gp_obj.grease_pencil_modifiers.new("Array", 'GP_ARRAY')
array.count = 5
array.offset = (1.0, 0.0, 0.0)
```

### 6. Animate Grease Pencil frame by frame

```python
import bpy
import math

gp_obj = bpy.context.active_object
gp_data = gp_obj.data
layer = gp_data.layers.active

total_frames = 24

for f in range(total_frames):
    frame = layer.frames.new(frame_number=f + 1)

    stroke = frame.strokes.new()
    stroke.display_mode = '3DSPACE'
    stroke.line_width = 8

    # Animate a circle that grows
    num_points = 32
    stroke.points.add(num_points)
    radius = 0.5 + (f / total_frames) * 2.0

    for i in range(num_points):
        angle = (2 * math.pi * i) / num_points
        x = radius * math.cos(angle)
        y = radius * math.sin(angle)
        stroke.points[i].co = (x, y, 0)
        stroke.points[i].pressure = 1.0
        stroke.points[i].strength = 1.0

# Set playback range
bpy.context.scene.frame_start = 1
bpy.context.scene.frame_end = total_frames
```

### 7. Configure drawing guides

```python
import bpy

# Guides are properties on the scene's tool settings
ts = bpy.context.scene.tool_settings
gp_settings = ts.gpencil_sculpt

# Access guide settings (when in Draw mode)
guide = ts.gpencil_stroke_placement_view3d

# Guide types are set via the tool settings
# Circular — concentric rings from reference point
# Radial — rays extending from reference point
# Parallel — constrained parallel lines
# Grid — horizontal/vertical grid lines
# Isometric — isometric angle constraints

# Note: Guides are interactive Draw mode features.
# For programmatic geometry, compute constrained points directly:
import math

def snap_to_grid(point, spacing=1.0):
    return tuple(round(c / spacing) * spacing for c in point)

def snap_to_radial(point, center=(0, 0, 0), num_rays=8):
    dx, dy = point[0] - center[0], point[1] - center[1]
    angle = math.atan2(dy, dx)
    snap_angle = round(angle / (2 * math.pi / num_rays)) * (2 * math.pi / num_rays)
    dist = math.sqrt(dx**2 + dy**2)
    return (center[0] + dist * math.cos(snap_angle),
            center[1] + dist * math.sin(snap_angle),
            point[2])
```

## Examples

### Example 1: Procedural comic panel with text

**User request:** "Create a simple comic panel layout with borders and speech bubble"

```python
import bpy
import math

def clear_scene():
    bpy.ops.object.select_all(action='SELECT')
    bpy.ops.object.delete()

clear_scene()

# Create GP object
gp_data = bpy.data.grease_pencils.new("ComicPanel")
gp_obj = bpy.data.objects.new("ComicPanel", gp_data)
bpy.context.collection.objects.link(gp_obj)

# Materials
mat_black = bpy.data.materials.new("GP_Black")
bpy.data.materials.create_gpencil_data(mat_black)
mat_black.grease_pencil.color = (0, 0, 0, 1)
mat_black.grease_pencil.show_fill = False
gp_obj.data.materials.append(mat_black)

mat_bubble = bpy.data.materials.new("GP_Bubble")
bpy.data.materials.create_gpencil_data(mat_bubble)
mat_bubble.grease_pencil.color = (0, 0, 0, 1)
mat_bubble.grease_pencil.fill_color = (1, 1, 1, 1)
mat_bubble.grease_pencil.show_fill = True
gp_obj.data.materials.append(mat_bubble)

# Panel border layer
border_layer = gp_data.layers.new("Borders")
border_frame = border_layer.frames.new(frame_number=1)

def draw_rect(frame, x, y, w, h, mat_idx=0, width=12):
    stroke = frame.strokes.new()
    stroke.display_mode = '3DSPACE'
    stroke.line_width = width
    stroke.material_index = mat_idx
    stroke.points.add(5)
    corners = [(x, y, 0), (x+w, y, 0), (x+w, y+h, 0), (x, y+h, 0), (x, y, 0)]
    for i, co in enumerate(corners):
        stroke.points[i].co = co
        stroke.points[i].pressure = 1.0
        stroke.points[i].strength = 1.0

# Outer border
draw_rect(border_frame, 0, 0, 6, 4)
# Inner panels (2 panels side by side)
draw_rect(border_frame, 0.2, 0.2, 2.7, 3.6)
draw_rect(border_frame, 3.1, 0.2, 2.7, 3.6)

# Speech bubble layer
bubble_layer = gp_data.layers.new("Bubbles")
bubble_frame = bubble_layer.frames.new(frame_number=1)

stroke = bubble_frame.strokes.new()
stroke.display_mode = '3DSPACE'
stroke.line_width = 6
stroke.material_index = 1
num_pts = 24
stroke.points.add(num_pts)
cx, cy, rx, ry = 4.5, 3.0, 0.8, 0.4
for i in range(num_pts):
    angle = (2 * math.pi * i) / num_pts
    stroke.points[i].co = (cx + rx * math.cos(angle), cy + ry * math.sin(angle), 0)
    stroke.points[i].pressure = 1.0
    stroke.points[i].strength = 1.0

bpy.ops.wm.save_as_mainfile(filepath="/tmp/comic_panel.blend")
```

### Example 2: Animated handwriting effect

**User request:** "Create an animation that draws text stroke by stroke like handwriting"

```python
import bpy

def clear_scene():
    bpy.ops.object.select_all(action='SELECT')
    bpy.ops.object.delete()

clear_scene()

bpy.ops.object.gpencil_add(type='EMPTY')
gp_obj = bpy.context.active_object
gp_data = gp_obj.data

# Material
mat = bpy.data.materials.new("GP_Ink")
bpy.data.materials.create_gpencil_data(mat)
mat.grease_pencil.color = (0.05, 0.05, 0.15, 1)
gp_data.materials.append(mat)

layer = gp_data.layers.active
frame = layer.frames.new(frame_number=1) if not layer.frames else layer.frames[0]

# Define letter paths as point sequences (simplified "HI")
letters = {
    'H': [(0,0,0),(0,2,0),(0,1,0),(1,1,0),(1,2,0),(1,0,0)],
    'I': [(2.5,2,0),(2.5,0,0)],
}

for letter, points in letters.items():
    stroke = frame.strokes.new()
    stroke.display_mode = '3DSPACE'
    stroke.line_width = 10
    stroke.material_index = 0
    stroke.points.add(len(points))
    for i, co in enumerate(points):
        stroke.points[i].co = co
        stroke.points[i].pressure = 1.0
        stroke.points[i].strength = 1.0

# Add Build modifier for animated reveal
build = gp_obj.grease_pencil_modifiers.new("Build", 'GP_BUILD')
build.mode = 'SEQUENTIAL'
build.start_frame = 1
build.length = 60

bpy.context.scene.frame_start = 1
bpy.context.scene.frame_end = 60

bpy.ops.wm.save_as_mainfile(filepath="/tmp/handwriting.blend")
```

## Guidelines

- Use `bpy.data.grease_pencils.new()` for data-level creation. Use `bpy.ops.object.gpencil_add()` for quick object creation with defaults.
- Always create at least one material and assign it before rendering — GP objects without materials render invisible.
- Stroke `display_mode` controls coordinate space: `3DSPACE` for world-space strokes, `2DSPACE` for screen-relative. Use `3DSPACE` for most scripted workflows.
- The `pressure` property on points controls line thickness variation. Set to 1.0 for uniform width, vary between 0.0-1.0 for pen-like tapering.
- GP modifiers use `grease_pencil_modifiers` (not `modifiers`). Type constants are prefixed with `GP_` (e.g., `GP_THICK`, `GP_SMOOTH`).
- For frame-by-frame animation, create separate `layer.frames.new(frame_number=N)` entries. Each frame holds independent strokes.
- The Build modifier is the easiest way to animate stroke reveal without per-frame scripting.
- Grease Pencil objects support the same transform operations as mesh objects (location, rotation, scale, parenting, constraints).
- For complex 2D art, organize content across multiple layers (outlines, fills, colors, effects) just like in traditional digital art software.

Related Skills

blender-vse-pipeline

26
from TerminalSkills/skills

Automate video editing in Blender's Video Sequence Editor with Python. Use when the user wants to add video, image, or audio strips, create transitions, apply effects, build edit timelines, batch assemble footage, estimate render times, or script any VSE workflow from the command line.

blender-scripting

26
from TerminalSkills/skills

Write and run Blender Python scripts for 3D automation and procedural modeling. Use when the user wants to automate Blender tasks, create 3D models from code, run headless scripts, manipulate scenes, batch process .blend files, build geometry with bmesh, apply modifiers, generate procedural shapes, or import/export 3D models using the bpy API.

blender-render-automation

26
from TerminalSkills/skills

Automate Blender rendering from the command line. Use when the user wants to set up renders, batch render scenes, configure Cycles or EEVEE, set up cameras and lights, render animations, create materials and shaders, or build a render pipeline with Blender Python scripting.

blender-motion-capture

26
from TerminalSkills/skills

Automate motion capture and tracking workflows in Blender with Python. Use when the user wants to import BVH or FBX mocap data, retarget motion to armatures, track camera or object motion from video, solve camera motion, clean up motion capture data, or script any tracking pipeline in Blender.

blender-compositing

26
from TerminalSkills/skills

Automate Blender compositing and post-processing with Python. Use when the user wants to set up compositor nodes, add post-processing effects, color correct renders, combine render passes, apply blur or glare, key green screens, create node-based VFX pipelines, or script the Blender compositor.

blender-animation

26
from TerminalSkills/skills

Animate 3D objects and characters in Blender with Python. Use when the user wants to keyframe properties, create armatures and rigs, set up IK/FK chains, animate shape keys for facial animation, edit F-Curves, use the NLA editor to blend actions, add drivers for expression-based animation, or script any animation workflow in Blender.

blender-addon-dev

26
from TerminalSkills/skills

Build custom Blender add-ons with Python. Use when the user wants to create a Blender add-on, register operators, build UI panels, add custom properties, create menus, package an add-on for distribution, or extend Blender with custom tools and workflows.

zustand

26
from TerminalSkills/skills

You are an expert in Zustand, the small, fast, and scalable state management library for React. You help developers manage global state without boilerplate using Zustand's hook-based stores, selectors for performance, middleware (persist, devtools, immer), computed values, and async actions — replacing Redux complexity with a simple, un-opinionated API in under 1KB.

zoho

26
from TerminalSkills/skills

Integrate and automate Zoho products. Use when a user asks to work with Zoho CRM, Zoho Books, Zoho Desk, Zoho Projects, Zoho Mail, or Zoho Creator, build custom integrations via Zoho APIs, automate workflows with Deluge scripting, sync data between Zoho apps and external systems, manage leads and deals, automate invoicing, build custom Zoho Creator apps, set up webhooks, or manage Zoho organization settings. Covers Zoho CRM, Books, Desk, Projects, Creator, and cross-product integrations.

zod

26
from TerminalSkills/skills

You are an expert in Zod, the TypeScript-first schema declaration and validation library. You help developers define schemas that validate data at runtime AND infer TypeScript types at compile time — eliminating the need to write types and validators separately. Used for API input validation, form validation, environment variables, config files, and any data boundary.

zipkin

26
from TerminalSkills/skills

Deploy and configure Zipkin for distributed tracing and request flow visualization. Use when a user needs to set up trace collection, instrument Java/Spring or other services with Zipkin, analyze service dependencies, or configure storage backends for trace data.

zig

26
from TerminalSkills/skills

Expert guidance for Zig, the systems programming language focused on performance, safety, and readability. Helps developers write high-performance code with compile-time evaluation, seamless C interop, no hidden control flow, and no garbage collector. Zig is used for game engines, operating systems, networking, and as a C/C++ replacement.