1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
|
"""
Using pycairo with moderngl.
We simply create a screen aligned quad with texture coordinates
to render the uploaded texture from cairo.
Textures in OpenGL are stored "upside-down" so we build
a vertex array with inverted y coordinates
"""
import math
from array import array
import cairo
import moderngl
from _example import Example
class CairoExample(Example):
title = "Cairo Integration"
aspect_ratio = 1.0
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.texture = self.render_cairo_to_texture(512, 512)
self.prog = self.ctx.program(
vertex_shader="""
#version 330
in vec3 in_position;
in vec2 in_texcoord_0;
out vec2 uv;
void main() {
gl_Position = vec4(in_position, 1.0);
uv = in_texcoord_0;
}
""",
fragment_shader="""
#version 330
uniform sampler2D texture0;
in vec2 uv;
out vec4 outColor;
void main() {
outColor = texture(texture0, uv);
}
""",
)
# Create a simple screen rectangle. The texture coordinates
# are reverted on the y axis here to make the cairo texture appear correctly.
vertices = [
# x, y | u, v
-1, 1, 0, 0,
-1, -1, 0, 1,
1, 1, 1, 0,
1, -1, 1, 1,
]
self.screen_rectangle = self.ctx.vertex_array(
self.prog,
[
(
self.ctx.buffer(array('f', vertices)),
'2f 2f',
'in_position', 'in_texcoord_0',
)
],
)
def render(self, time, frame_time):
self.texture.use(location=0)
self.screen_rectangle.render(mode=moderngl.TRIANGLE_STRIP)
def render_cairo_to_texture(self, width, height):
# Draw with cairo to surface
x, y, radius = (250, 250, 200)
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height)
ctx = cairo.Context(surface)
ctx.set_line_width(15)
ctx.arc(x, y, radius, 0, 2.0 * math.pi)
ctx.set_source_rgb(0.8, 0.8, 0.8)
ctx.fill_preserve()
ctx.set_source_rgb(1, 1, 0)
ctx.stroke()
ctx.move_to(20, 30)
ctx.select_font_face("Purisa", cairo.FONT_SLANT_NORMAL,
cairo.FONT_WEIGHT_NORMAL)
ctx.set_font_size(13)
ctx.set_source_rgb(0.8, 0.8, 0.8)
ctx.show_text("Example Text")
# Copy surface to texture
texture = self.ctx.texture((width, height), 4, data=surface.get_data())
texture.swizzle = 'BGRA' # use Cairo channel order (alternatively, the shader could do the swizzle)
return texture
if __name__ == "__main__":
CairoExample.run()
|