我正在尝试渲染一个可爱的小直角三角形,该三角形带有我想围绕其质心旋转的斜边。为此,我使用 cairocffi 在 python 中工作,cairocffi 是 cairo C 库的 python 实现。
为了实现这一点,我使用了 3 个从边缘定向并指向质心的线性渐变。通过这样做,我实现了以下目标:
http://i.imgur.com/WswcCg6.png
这张图片在左侧显示了最终产品,在右侧显示了我用来实现它的构造线和阴影三角形段。
我遇到的问题是不同旋转角度的渐变渲染行为不一致,因此当我将动画图像串在一起时,三角形内的渐变“抖动”。您可以在以下链接中找到演示此行为的视频。如您所见,三角形边缘流畅,只有渐变抖动。
我用来实现这一点的代码如下。非常感谢任何有关找出可能出现问题的帮助。
import math
import cairocffi as cairo
import array
def prism90(size, angle):
DIMENSION = size
height = 0.44
data = array.array('c', chr(0) * DIMENSION * DIMENSION * 4)
stride = DIMENSION * 4
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, DIMENSION, DIMENSION, data, stride)
# Context
ctx = cairo.Context(surface)
ctx.scale (DIMENSION, DIMENSION)
# black background for .png
ctx.rectangle (0, 0, 1, 1)
ctx.set_source_rgba(0.0, 0.0, 0.0, 1.0)
ctx.fill ()
ctx.translate(0.5, 0.5)
ctx.rotate(math.radians(angle))
ctx.set_operator(cairo.OPERATOR_ADD)
trigons = [
[(0,0),(0,-height+height/2),( height,height/2)],
[(0,0),(0,-height+height/2),(-height,height/2)],
[(0,0),(height, height/2),(-height,height/2)],
]
gradients = [
( height/2, 0, 0, height-height/2),
(-height/2, 0, 0, height-height/2),
( 0, height-height/2, 0, 0),
]
steps = 3
stop_start = 0.01
stop_inc = 0.025
alpha_start = 0.3
alpha_inc = 0.15
shade = 0.6
for index, (points, gradient) in enumerate(zip(trigons, gradients)):
if index == 2: # deeper gradient for hypotenuse trigon
steps = steps*2-1
alpha_start = 0.4
alpha_inc = 0.05
gradient = cairo.LinearGradient(*gradient)
for step in xrange(0, steps, 1):
stop = stop_start+stop_inc*step
alpha = alpha_start+alpha_inc*step
gradient.add_color_stop_rgba(stop, shade, shade, shade, alpha)
ctx.set_source(gradient)
ctx.move_to(*points[0])
ctx.line_to(*points[1])
ctx.line_to(*points[2])
ctx.close_path()
ctx.fill()
shade = shade +0.1
cols = [(1,0,0), (0,1,0), (0,0,1)]
for grad, col in zip(gradients, cols):
ctx.set_line_width(1./size*1)
ctx.set_source_rgb(*col)
ctx.move_to(grad[0], grad[1])
ctx.line_to(grad[2], grad[3])
ctx.stroke()
surface.flush()
surface.write_to_png ("prism90_"+str(angle)+".png")
surface.finish()
return data.tostring()
angle = 0
prism = prism90(250,angle)