Skip to content

Instantly share code, notes, and snippets.

@lampysprites
Last active March 7, 2021 16:04
Show Gist options
  • Save lampysprites/90171771a82bd0fc55bda9e75fd4dd47 to your computer and use it in GitHub Desktop.
Save lampysprites/90171771a82bd0fc55bda9e75fd4dd47 to your computer and use it in GitHub Desktop.
Screen space affine texture mapping in Blender
import bpy
import bmesh
# THIS SCRIPT WILL RENDER THE ANIMATION USING THE SCENE'S OUTPUT SETTINGS
# DURING THE RENDER BLENDER WILL APPEAR TO FREEZE
# TO SEE THE EFFECT, SET UP MATERIAL TEXTURES LIKE THIS:
#+-------------+ +------------------+ +-----------------+
#|UV MAP | |SEPARATE XYZ | |DIVIDE |
#| UV *|-----| X *|----------|* Value Value *|\
#| | | Y *|\ -|* Value | -\ +-------------+
#|*uvz | | Z .| \ / | | -\ COMBINE XYZ | +-------------+
#+-------------+ +------------------+ -\ -/ +-----------------+ -|* X | |TEXTURE |
# \/ -|* Y | | |
# /\ / |. Z Vector*|-- |* Vector |
#+-------------+ +------------------+ -/ -\ +-----------------+ -/ | | | |
#|UV MAP | |SEPARATE XYZ | / \ |DIVIDE | / | | | |
#| UV *|-----| X *|/----\ -|* Value Value *|/ | | +-------------+
#| | | Y .| ----|* Value | +-------------+
#|*z | | Z .| | |
#+-------------+ +------------------+ +-----------------+
# BY twitter.com/lampysprites
render_animation = True
def wobble_uvs(mesh):
context = bpy.context
cam = bpy.data.objects["Camera"]
bm = bmesh.new()
bm.from_mesh(mesh)
if "z" in bm.loops.layers.uv.keys():
bm.loops.layers.uv.remove(bm.loops.layers.uv.get("z"))
if "uvz" in bm.loops.layers.uv.keys():
bm.loops.layers.uv.remove(bm.loops.layers.uv.get("uvz"))
uv_layer = bm.loops.layers.uv.active
if not uv_layer:
return
uvz_layer = bm.loops.layers.uv.new("uvz")
z_layer = bm.loops.layers.uv.new("z")
for face in bm.faces:
for loop in face.loops:
to_cam = (context.object.matrix_world @ loop.vert.co) - cam.location
w = to_cam.dot(to_cam) ** -.5
loop[uvz_layer].uv = loop[uv_layer].uv * w
loop[z_layer].uv.x = w
bm.to_mesh(mesh)
# one frame
for mesh in bpy.data.meshes:
wobble_uvs(mesh)
# render frames
if render_animation:
scene = bpy.context.scene
outpath = scene.render.filepath
for frame in range(scene.frame_start, scene.frame_end + 1):
scene.render.filepath = outpath + str(frame).zfill(4)
scene.frame_set(frame)
for mesh in bpy.data.meshes:
wobble_uvs(mesh)
bpy.ops.render.render(write_still=True)
scene.render.filepath = outpath
@lampysprites
Copy link
Author

o yeh there's a bug with using context.object at line 46, should be the mesh object instead

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment