Skip to content

着色器与高级渲染 ​

本页属于 GenPy Ren'Py 学习路线。教程内容面向 Ren'Py 8.x,并在页面末尾连接到 GenPy 的对应工作流。

学习目标 ​

  • 了解“着色器与高级渲染”在 Ren'Py 项目中的用途。
  • 能在一个最小项目里验证本章相关语法或工作流。
  • 知道发布前需要检查的常见风险,并能在 GenPy 中继续维护。

核心语法 ​

  • mesh True
  • shader
  • renpy.register_shader
  • uniform
  • GLSL
  • Model-Based Rendering

可运行示例 ​

text
transform crt:
    mesh True
    shader "example.scanline"

show bg room at crt

教程正文 ​

当内置变换(ATL、matrixcolor、blur)还不够时,可用 基于模型的渲染(Model-Based Rendering) 写自定义 GLSL 着色器,做出 CRT 扫描线、色散、水波、溶解、光照等效果。 本章是入门导引——着色器是图形编程,落地前请对照官方 Model-Based Rendering 文档逐字校验。

1. 开启模型渲染 ​

普通图像是“贴图”;加上 mesh=True 后,它变成一个可被着色器处理的“模型”:

text
transform crt:
    mesh True
    shader "example.scanline"

show bg room at crt
  • mesh True:把可显示物切成网格、走模型渲染管线(着色器才能生效)。
  • shader "...":应用一个已注册的着色器 part(可多个)。
  • blur(第 31 章)本质也是 model 渲染,是最易用的“内置着色器”。

2. 注册自定义着色器:renpy.register_shader ​

着色器由若干 part 组成,每个 part 声明变量并提供顶点/片段代码片段,按 优先级 拼接:

  • 优先级约定:100 建立几何,200 决定初始片段颜色(gl_FragColor), 更高的优先级在此基础上叠加效果。
  • 关键字参数以 vertex_ 或 fragment_ 开头、以整数优先级结尾,如 fragment_300。
  • 变量命名约定:uniform 用 u_、attribute 用 a_、varying 用 v_ 前缀。

官方示例:横向渐变(逐字可用) ​

text
init python:
    renpy.register_shader("example.gradient", variables="""
        uniform vec4 u_gradient_left;
        uniform vec4 u_gradient_right;
        uniform vec2 u_model_size;
        varying float v_gradient_done;
        attribute vec4 a_position;
    """, vertex_300="""
        v_gradient_done = a_position.x / u_model_size.x;
    """, fragment_300="""
        float gradient_done = v_gradient_done;
        gl_FragColor *= mix(u_gradient_left, u_gradient_right, gradient_done);
    """)

transform gradient:
    shader "example.gradient"
    u_gradient_left (1.0, 0.0, 0.0, 1.0)
    u_gradient_right (0.0, 0.0, 1.0, 1.0)

# 用法
show eileen happy at gradient

在 transform 里直接写 u_xxx (...) 就能给着色器的 uniform 传参。

3. 标准变量(着色器里可直接用) ​

Ren'Py 会自动提供这些常用变量,你在 variables 里声明后即可使用:

变量含义
sampler2D tex0(tex1/tex2)第 1/2/3 张纹理
attribute vec2 a_tex_coord顶点对应的纹理坐标
varying vec2 v_tex_coord片段的纹理坐标
gl_FragColor输出像素颜色(在 fragment 里写它)
vec2 u_model_size模型尺寸
float u_lod_bias纹理 LOD 偏置

简易扫描线(基于标准变量,自行校验) ​

text
init python:
    renpy.register_shader("example.scanline", variables="""
        uniform sampler2D tex0;
        uniform vec2 u_model_size;
        varying vec2 v_tex_coord;
    """, fragment_300="""
        float scan = 0.92 + 0.08 * sin(v_tex_coord.y * u_model_size.y * 3.1416);
        gl_FragColor.rgb *= scan;
    """)

transform scanline:
    mesh True
    shader "example.scanline"

priority 200 已把纹理颜色填进 gl_FragColor,我们在 300 处再乘以扫描明暗。

4. 常见高级效果(思路) ​

效果思路
CRT / 扫描线按 y 周期性压暗 + 轻微桶形畸变
色散 / 故障R/G/B 三通道用不同偏移采样 tex0
水波 / 热浪用 sin(time + coord) 扰动采样坐标
溶解 / 过渡按噪声纹理阈值控制 alpha
光照顶点法线 + 光源方向点乘(见官方 lighting 示例)

时间驱动动画着色器需要 u_time 之类 uniform,并配合 mesh/Model,详见官方 “Animated Shaders”。

5. 用现成的就好 ​

自己写 GLSL 门槛高。社区有大量开源 Ren'Py 着色器(itch.io、GitHub、Lemma Soft), 覆盖 CRT、雨滴、色差、辉光等,直接 register_shader 引入即可——优先复用、再改造。

常见坑 ​

  • 着色器是 GPU 代码,写错通常是“黑屏/不显示”而非报错,逐步加效果调试。
  • Web/移动端 GPU 能力参差,复杂着色器务必真机实测并提供降级开关。
  • 变量名严格遵循 u_/a_/v_ 约定;标准变量名(tex0/v_tex_coord/gl_FragColor)不要拼错。
  • 多个 shader part 共享同名变量会相互影响,注意命名避免冲突。
  • GLSL 版本与精度(precision)在不同平台有差异,参考官方“GLSL Version”。

官方参考 ​

在 GenPy 里怎么做 ​

  • 在 GenPy 的代码模式中维护相关 .rpy 文件,先保持语法清晰,再逐步加入本章功能。
  • 用故事图谱、变量、校验或演出编辑器把“能运行”提升到“可维护”。
  • 导出前结合 Ren'Py Lint 和 GenPy 校验结果,确认脚本、素材和发布路径一致。

推荐继续阅读:

Built for GenPy creators.