1 # SPDX-License-Identifier: GPL-2.0-or-later
5 from mathutils
import Vector
, Matrix
6 from mathutils
.geometry
import tessellate_polygon
7 from gpu_extras
.batch
import batch_for_shader
10 def export(filepath
, face_data
, colors
, width
, height
, opacity
):
11 offscreen
= gpu
.types
.GPUOffScreen(width
, height
)
15 fb
= gpu
.state
.active_framebuffer_get()
16 fb
.clear(color
=(0.0, 0.0, 0.0, 0.0))
17 draw_image(face_data
, opacity
)
19 pixel_data
= fb
.read_color(0, 0, width
, height
, 4, 0, 'UBYTE')
20 pixel_data
.dimensions
= width
* height
* 4
21 save_pixels(filepath
, pixel_data
, width
, height
)
27 def draw_image(face_data
, opacity
):
28 gpu
.state
.blend_set('ALPHA')
30 with gpu
.matrix
.push_pop():
31 gpu
.matrix
.load_matrix(get_normalize_uvs_matrix())
32 gpu
.matrix
.load_projection_matrix(Matrix
.Identity(4))
34 draw_background_colors(face_data
, opacity
)
37 gpu
.state
.blend_set('NONE')
40 def get_normalize_uvs_matrix():
41 '''matrix maps x and y coordinates from [0, 1] to [-1, 1]'''
42 matrix
= Matrix
.Identity(4)
50 def draw_background_colors(face_data
, opacity
):
51 coords
= [uv
for uvs
, _
in face_data
for uv
in uvs
]
52 colors
= [(*color
, opacity
) for uvs
, color
in face_data
for _
in range(len(uvs
))]
56 for uvs
, _
in face_data
:
57 triangles
= tessellate_uvs(uvs
)
58 indices
.extend([index
+ offset
for index
in triangle
] for triangle
in triangles
)
61 shader
= gpu
.shader
.from_builtin('2D_FLAT_COLOR')
62 batch
= batch_for_shader(
64 {"pos": coords
, "color": colors
},
70 def tessellate_uvs(uvs
):
71 return tessellate_polygon([uvs
])
74 def draw_lines(face_data
):
76 for uvs
, _
in face_data
:
77 for i
in range(len(uvs
)):
79 end
= uvs
[(i
+ 1) % len(uvs
)]
80 coords
.append((start
[0], start
[1]))
81 coords
.append((end
[0], end
[1]))
83 shader
= gpu
.shader
.from_builtin('POLYLINE_UNIFORM_COLOR')
84 shader
.uniform_float("viewportSize", gpu
.state
.viewport_get()[2:])
85 shader
.uniform_float("lineWidth", 1.0)
86 shader
.uniform_float("color", (0.0, 0.0, 0.0, 1.0))
88 batch
= batch_for_shader(shader
, 'LINES', {"pos": coords
})
92 def save_pixels(filepath
, pixel_data
, width
, height
):
93 image
= bpy
.data
.images
.new("temp", width
, height
, alpha
=True)
94 image
.filepath
= filepath
95 image
.pixels
= [v
/ 255 for v
in pixel_data
]
97 bpy
.data
.images
.remove(image
)