Ren'Py中包含一个文本着色器(text shader)系统,可以控制文本的显示效果。 启用文本着色器系统后,会使用两个三角面片 :doc:`model` 来渲染每一个Unicode字符。 创作者自定义或Ren'Py内置的着色器程序都可以通过这种方式应用在模型上,并控制文本显示效果。
文本着色器的文档有三块内容:
需要注意,文本着色器系统本身不复杂,游戏创作者可以很容易掌握。 但制作符合自己要求的文本着色器需要很多基础知识,比如GLSL(OpenGL Shading Language)和 :doc:`model` 等。 其中大部分基础知识都与Ren'Py的功能特性无关。
总共有三种方法可以使用文本着色器:
默认文本着色器 第一种方法,使用 :var:`config.default_textshader` 设置默认的文本着色器。
define config.default_textshader = "wave:10"
这样设置后,指定的文本着色器将用于所有文本,除了某些额外指定了文本着色器的内容。 该设置项还可以合并多个文本着色器,其中大部分都是默认着色器。
默认文本着色器需要小心慢速文本的情况,并且不应产生副作用。
样式 第二种方法,使用样式特性 :propref:`textshader`。可以直接指定样式特性,也可以使用Ren'Py提供的多种样式设置方式。
style default: textshader "dissolve" define goldfinger = Character("金手指", what_textshader="linetexture:gold.png") screen purchase(): vbox: text "购买DLC内容!" textshader "wave" textbutton "立刻购买": text_textshader "wave" action iap.Purchase("dlc")
文本标签 第三种方法,使用 :tt:`对应的文本标签 <shader>` 修改部分文本的显示效果。
"这是什么? {shader=zoom}突然出现{/shader} 的一封信?"
注意 一个文本段落要么都使用文本着色器,要么都不使用,不能混着用。 例如,应该通过设置 :var:`config.default_textshader` 或样式特性 :propref:`textshader`,再使用文本标签显示效果。
在脚本中可以使用字符串来指定文本着色器:
"dissolve" "jitter:u__jitter=1.0, 3.0" "texture:gold.png"
字符串的第一部分,即第一个冒号前的内容,表示文本着色器的名称。 字符串的其他部分,对应传给着色器的一些uniform变量,使用冒号分隔。 (uniform变量是着色器程序的控制变量。)
uniform变量可以使用等号(=)赋值。也可以省略uniform变量名,按顺序依次对所有uniform变量赋值。(Ren'Py 7不支持省略uniform变量名。) 所有内置变量名均以 u_ 开头,处于简洁也可以省略这个 u_ 。
uniform变量的值可能是以下类型:
uniform值不能使用表达式或从某个变量读取,但可以使用文本内插创建一个字符串并计算出某个文本着色器的标签或参数。
最后,文本着色器可以使用 | 符号联用。例如:
"jitter:1.0, 3.0|wave"
上面这句脚本会在文本中同时应用jitter和wave两个着色器,前提是两个着色器互相兼容,并且没有同名的uniform变量 (或具有同名且同类型的uniform变量,能够互相兼容,取值固定使用着色器列表中最后一个同名uniform变量的值)。
除非文本着色器显式将 include_default 设置为False,通过样式或文本标签应用文本着色器时都将联用默认的文本着色器。
配置项 :var:`config.textshader_callbacks` 可以设置回调函数,在启用某个文本着色器之后就会调用设置的回调函数。 该功能可以基于个人设置(preference)定制文本着色器。
default persistent.dissolve_text = True init python: def get_default_textshader(): if persistent.dissolve_text: return "dissolve" else: return "typewriter" define config.default_textshader = "default" define config.textshader_callbacks["default"] = get_default_textshader
以下是Ren'Py内建的文本着色器:
.. function:: dissolve dissolve文本着色器可以将文本以溶解(dissolve)形式缓慢显示出来。dissolve指定范围的字符,按顺序依次显示,直到显示完最后一个字符。 `u__duration = 10.0` 过渡效果持续时间。若设为0,立刻显示没有过渡效果。
.. function:: flip flip文本着色器会将文本在水平方向上翻转。开头的字符先翻转,最后的字符最后翻转。 `u__duration = 10.0` 过渡效果持续时间。若设为0,立刻翻转没有过渡效果。
.. function:: jitter jitter文本着色器会让文本抖动,即根据文本原显示位置添加一个随机偏移量,且每帧的位置偏移量都重新计算。 `u__jitter=(3.0, 3.0)` 抖动幅度,单位为像素。
.. function:: linetexture 将文本与某个纹理相乘,各行单独计算。用到的纹理在水平方向会与文本左端对齐。 纹理的中心点在垂直方向上会与文本底部对齐,这也意味着纹理下半部分几乎就看不到了。 `u__texture = ...` 与文本相乘使用的纹理。 `u__scale = (1.0, 1.0)` 纹理的缩放系数。例如(1.0, 0.5)可以让纹理变为原本的一半高度。
.. function:: offset offset文本着色器可以让文本位置偏移一个固定的值。 `u__offset = (0.0, 0.0)` 文本偏移量,单位为像素。
.. function:: slowalpha slowalpha着色器用于配合另一个慢速文本着色器,比如typewriter或dissolve。 它可以让未被其他文本着色器生效的文本内容以一个半透明的状态显示而不是完全不可见,即参数u__alpha的值。 `u__alpha = 0.2` 其他文本着色器还未生效部分的文本不透明度。
.. function:: texture texture文本着色器会将多行文本与某个纹理的颜色相乘。 它不对轮廓线(outline)和偏移(offset)生效。用到的纹理将与整段文本的左上角对齐。 `u__texture = ...` 与文本相乘使用的纹理。
.. function:: typewriter typewriter文本着色器配合低速文本,可以让字符逐个出现,模仿人类打字员的行为。 使用该着色器后,默认文本着色器将不生效。
.. function:: wave wave文本着色器可以让文本向波浪一样上下弹跳。 `u__amplitude = 5.0` 文本的上下位移幅度,单位为像素。 `u__frequency = 2.0` 移动频率,表示每秒完成整个弹跳的次数。 `u__wavelength = 20.0` 整个波长范围涉及的字符数。
.. function:: zoom zoom文本着色器可以让低速文本从某个初始大小逐步放大到完整尺寸。初始大小的值由参数u__zoom决定,默认为0.0。 `u__zoom = 0.0` 字符显示时的初始大小。 `u__duration = 10.0` 过渡效果持续时间。若设为0,立刻变大没有过渡效果。 使用该着色器后,默认文本着色器将不生效。
文本着色器是运行在GPU上的GLSL程序。可以使用 renpy.register_text_shader 函数注册文本着色器。
.. function:: renpy.register_textshader(name, shaders=(), extra_slow_time=0.0, extra_slow_duration=0.0, redraw=None, redraw_when_slow=0.0, include_default=True, adjust_function=None, doc=None, **kwargs) 该函数会创建一个文本着色器,并注册着色器名 `name` 。 该函数使用下列入参: `name` 文本着色器名。同时也会注册一个名为 `name` 的着色器程序。 `shaders` 应用到文本的着色器程序。该项可以是一个字符串,字符串列表或字符串元组。 该项中包含的着色器程序必须是通过 :func:`renpy.register_shader` 或本函数注册过的着色器。 如果着色器名前带一个‘-’,表示从着色器列表中移除对应的着色器程序。 (例如,“-textshader.typewriter”表示移除typerwriter着色器。) 注意,通过该函数注册的着色器名自动添加了前缀“textshader.”,在作为参数时需要传入完整的着色器名。 `extra_slow_time` 添加一个额外的时间。Ren'Py计算当前字符的效果时间时将加上该时间。 某些着色器做字符过渡效果时间不足时,该参数就可以用上。 `extra_slow_duration` 该参数也是一个时间值,会除以同时生效字符总数然后再加到 `extra_slow_time` 上。 `redraw` 所有低速文本显示并且经过 `extra_slow_time` 时间后,再次重新绘制的时间间隔,单位为秒。 `redraw_when_slow` 文本已绘制并且显示低速文本时,再次重新绘制的时间间隔,单位为秒。 `include_default` 若为True,将会联用 :var:`config.default_textshader` 中的着色器。 `adjust_function` 该参数是一个函数,通过某个对象调用。传给文本着色器的uniform变量会先使用该函数处理。 该函数可以设置来源对象的 `extra_slow_time`、`extra_slow_duration`、 `redraw` 和 `redraw_when_slow` 这4个字段。 `doc` 包含文档信息的一个字符串。该参数为Ren'Py的文档系统所设计。 以 ``u_`` 开头的关键字入参会传给着色器作为uniform变量,以 ``#`` 开头的字符串会识别为某种颜色。 大多数uniform变量都应该以 ``u__`` 开头,使用 :ref:`着色器本地变量 <shader-local-variables>` 防止与其他着色器发生变量名冲突。 名为 `variables` 的关键字入参和所有以 `fragment_`、`vertex_` 开头的关键字入参都会传给 :func:`renpy.register_shader` 函数, 并注册对应的着色器。
除了创作者自己设计文本着色器时指定的uniform变量(通常以 u__
开头),Ren'Py还使下列变量可以直接在文本着色器中使用。
若要在文本着色器中使用某个变量,需要将变量名通过 variables 参数传入 renpy.register_text_shader 函数。
除此之外,针对模型还可以使用 :ref:`uniform和attribute变量 <model-uniforms>`, 常用的包括 a_position、a_tex_coord、u_time 和 u_random。
float u_text_depth
float u_text_main
float u_text_max_depth
vec2 u_text_offset
float u_text_outline
float u_text_slow_duration
float u_text_slow_time
float u_text_to_drawable
float u_text_to_virtual
sampler2D tex0
vec2 res0
绘制文本时,每个字形(glyph)都有自身对应的顶点(vertex)。多个字形可能会有一些顶点的坐标是相同的,但依然会看作不同顶点传入着色器。
(译者注:baseline、ascent和descent是字母型文字才需要考虑的东西,纯中文用户完全不用管。)
float a_text_ascent
vec2 a_text_center
float a_text_descent
float a_text_index
vec2 a_text_min_time
u_text_slow_duration
的值又不是0.0,该项应设置为-3600.0。vec2 a_text_max_time
u_text_slow_duration
的值又不是0.0,该项应设置为-3600.0。float a_text_time
u_text_slow_duration
的值又不是0.0,该项应设置为-3600.0。vec4 a_text_pos_rect
res0
来获得纹理坐标值。Ren'Py绘制带轮廓线的文本时,会创建覆盖文本开头和结尾的伪字形(pseudo-glyph)。 如果遇到空行,则会创建覆盖整行的伪字形。 这些伪字形用于计算轮廓线超出文字顶部和底部的区域。
这是一个文本着色器样例,能让文本显示后转动。
init python: def adjust_extra_slow_time(ts, u__delay, **kwargs): """ 调整文本着色器的额外显示时间,以支持旋转文本着色器。 """ ts.extra_slow_time = u__delay renpy.register_textshader( "spin", adjust_function = adjust_extra_slow_time, variables = """ uniform float u__delay; uniform float u__offset; uniform float u_text_slow_time; attribute vec2 a_text_center; attribute float a_text_min_time; """, vertex_50 = """ float l__angle = clamp((u_text_slow_time - a_text_min_time) / u__delay, 0.0, 1.0) * 2.0 * 3.1415926536; float l__sin = sin(l__angle); float l__cos = cos(l__angle); gl_Position.y -= u__offset; gl_Position.xy -= a_text_center; gl_Position = vec4( gl_Position.x * l__cos - gl_Position.y * l__sin, gl_Position.x * l__sin + gl_Position.y * l__cos, gl_Position.z, gl_Position.w ); gl_Position.xy += a_text_center; gl_Position.y += u__offset; """, u__delay = 1.0, u__offset = 0, )
之后就可以在如下脚本中使用:
define config.default_textshader = "typewriter" label start: "这是一个 {shader=spin:0.5:-5}旋转{/shader} 文本着色器测试。"
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。