モデルベースのレンダリング link

多くのビジュアルノベルのように Rend'Py では 2 次元の矩形画像が主に使用されていますが、内部には近代的な GPU に見られる機能を利用できるようにしたモデルベースのレンダラーがあります。これにより他では出来ない多くのビジュアルエフェクトを可能にします。

警告すると、これは Ren'Py の最も高度な機能の1つです。多くの場合でモデルベースのレンダリングが背後でどのように動いているかを理解する必要はなく、 matrixcolor や Live2D のような機能のサポートはモデルベースのレンダリングの動作を理解しなくても使用できます。しかし理解すればそのような機能を追加できるでしょう。このドキュメントはかなり高度な制作者または Ren'Py 本体に機能を追加したい開発者を対象とします。

モデルベースのレンダリングは Ren'Py の最も高度な機能の1つであり、このドキュメントは先に OpenGL, OpenGL ES, GLSL ES のマニュアルを読んでおかなければ理解が難しいでしょう。さらに直接 GPU ドライバーに渡される部分があり、それらは間違った入力も受け付けてしまうので、複数種類のハードウェアでのチェックが重要となります。

モデル、レンダリング、描画処理 link

Ren'Pyが画面に描画する基本的なものはモデルです。モデルは次の要素で構成されます :

  • 1つ以上の三角形のメッシュ。三角は3つの角となる頂点で構成され、それぞれ2次元、または三次元の位置を格納し、追加情報を持つ場合もあります。追加情報の多くはテクスチャの座標です。

  • 0枚以上のテクスチャー。ゲームで動作可能な正確な枚数は GPU によって制限されます。すべての GPU は 1 つのモデルにつき最低 3 つのテクスチャをサポートするはずです。テクスチャとは GPU に直接または render-to-texture 操作でロードされた 画像データを含む矩形のことです。

  • シェーダーパーツ名の一覧。Ren'Py はこれらのシェーダーパーツを使って、モデルをレンダリングするために GPU 上で実行されるプログラムであるシェーダーを作成します。シェーダーパーツの名前の前に "-" をつけると、そのシェーダーパーツを使用しないようにできます。

  • uniform 値。 uniform は、そのモデル全体で同じである追加データのです。例えば、モデルが solid カラーを表現するなら、その色は uniform です。

  • GL プロパティー。GL プロパティーは minification/magnification モードやカラーマスクのようなレンダリング方法をさらに制御するためのフラグです。

Ren'Py は通常複数のものを画面に描画するので、 Render オブジェクトのツリーを作成します。これらのレンダーオブジェクトは、モデルや他のレンダーを子として持てます ( 後述するように、レンダーオブジェクトをモデルにもできます)。レンダーは以下のものを含みます。 :

  • 各子に対して適用される2次元のオフセットを含む子のリスト

  • 3次元空間において、子がどのように transform されるかを記述した Matrix

  • 描画時にModelに適用されるシェーダーパーツ名のリスト、uniform、GLプロパティー

  • ポリゴンを切り取る描画可能空間が更新されるべきかどうかを決定するフラグ。

Ren'Py は、レンダーのツリーを深度優先で探索し、モデルに出会うまで画面を描画します。この探索の間、Ren'Pyはモデルの位置を transform する matrix, ポリゴンの切り取り、シェーダーパーツのリスト、uniform、gl プロパティーを更新します。この探索の過程で Model に遭遇すると、適切なシェーダプログラムが GPU 上で起動され、すべての情報が渡され、描画処理が実行されます。

どこでモデルが作成されるか link

Ren'Py は通常の操作の一環として、自動的にモデルを作成します。モデルがどこで作られるかを理解する主な理由は、モデルが描画操作に対応し、それゆえシェーダーが適用される単位となるからです。

画像と画像マニピュレータ

これらはメッシュを持つモデルを作成し、そのメッシュには画像の矩形をカバーする2つの三角形を含みます。そのメッシュにはテクスチャ座標も含みます。このモデルは "renpy.texture" シェーダを使用します。

Solid()

Solid Displayable は 2 つの三角形を含むメッシュを作成し、テクスチャ座標はありません。このモデルは "renpy.solid "シェーダーを使用し、その色は u_renpy_solid_color の uniform に配置されています。

Dissolve(), ImageDissolve(), AlphaDissolve(), Pixellate(), AlphaMask(), Flatten()

これらの transform と Displayable はそれぞれその目的に必要なメッシュ、シェーダー、 uniform を持つモデルを作成します。

Live2D

Live2D Displayable はレンダリング時に複数のモデルを作成し一般的にレイヤーごとに1つのモデルがあります。

Transform() and ATL

mesh が True または blur が使用されているなら、 Transform はモデルを作成します。この場合、Transform の子はテクスチャにレンダリングされ、そのモデルに関連するメッシュとして最初のテクスチャのメッシュが使用されます。

すべての transform がモデルを作成するわけではありません。いくつかの transform は単に Render にシェーダーや uniform を追加するだけです ( bluralpha を使用する transform など ) 。その他の transform は単純にジオメトリに影響を与えるものです。

Render

transform は mesh attribute が True ならモデルを作成します。この場合、その Render の子はテクスチャにレンダリングされ、そのモデルに関連するメッシュとして最初のテクスチャのメッシュが使用されます。

将来的にモデルを作成するさらに他の方法が Ren'Py に追加されると期待されます。

シェーダープログラムの生成 link

Ren'Py はまずシェーダーパーツ名のリストを組み立てて、シェーダープログラムを生成します。このリストは、 "renpy.geometry", レンダーから取得したシェーダーパーツのリスト、描画中のModelにあるシェーダーパーツのリストで構成されています。

その後、シェーダーパーツは重複排除されます。 "-" で始まるシェーダーパーツはリストから削除され、先頭の "-" を除いたものと同じシェーダーパーツも削除されます ( つまり "-renpy.geometry" はそれ自身と "renpy.geometry" を削除します ) 。

続いて Ren'Py は、シェーダーパーツのリストを受け取り、変数、関数、 vertex シェーダーパーツ、フラグメントシェーダーパーツのリストを取得します。これらは順番にシェーダーのソースコード生成に使われます。 vertex シェーダーとフラグメントシェーダーのパーツは、番号の小さいものから大きいものへと優先順位をつけて含まれます。

つまり、あるシェーダで作成された変数は、そのシェーダパーツのリストにある他のシェーダからのあらゆるフラグメントからアクセスできるようになります。 Python の関数のように、シェーダ間の干渉を防ぐためのスコープは存在しません。

Ren'Py はこれまでに使用されたすべてのシェーダーパーツの組み合わせを game/cache/shaders.txt にキャッシュしておき、起動時にそれらを読み込みます。シェーダーの使用に大きな変更があった場合は、このファイルを編集または削除して、有効なデータで再作成できるようするべきです。

カスタムシェーダーの作成 link

renpy.register_shader 関数を呼び出して GLSL シェーダーの部品を提供すると新しいシェーダーパーツが作成できます。

一般的に、シェーダーパーツは "mygame.recolor" や "mylibrary.warp" のような "namespace.part" の形式であるべきです。 "renpy." や "live2d." で始まる名前は _ で始まる始まるもの同様に Ren'Py で予約されています。

renpy.register_shader(name, **kwargs) link

これはシェーダーパーツの登録をします。 name とその後に続くキーワード引数を受け取ります。

name

登録するシェーダーパーツの名前の文字列です。アンダースコアや "renpy." で始まる名前は Ren'Py で予約されています。

variables

登録するシェーダーパーツで使用される変数です。これらは行ごとに (uniform や attribute, varying のような)ストレージに続いて、型、セミコロンとなるべきです。例

variables='''
uniform sampler2D tex0;
attribute vec2 a_tex_coord;
varying vec2 v_tex_coord;
'''
vertex_functions

指定するなら vertex シェーダーに含まれる関数を含める文字列です。

fragment_functions

指定するなら fragment シェーダーに含まれる関数を含める文字列です。

他のキーワード引数は "fragment_200" や "vertex_300" のように vertex_fragment_ から始まり、優先度を表す数値で終わるべきです。これらは優先度の数値順に適切なシェーダーに配置されるテキストを指定します。

Ren'Py では次の型の変数のみをサポートします。 :

  • float (Python float)

  • vec2 (2つの浮動小数のタプル)

  • vec3 (3 つの浮動小数のタプル)

  • vec4 ( 4 つの浮動小数のタプル)

  • mat4 (Matrix)

  • sampler2D (Ren'Py 提供 )

Uniform 変数は u_ で、 attribute は a_, varying 変数 は v_ で始めるべきです。 u_renpy_ や a_renpy、v_renpy で始まる変数は後述する標準的な変数同様に予約されています。

優先順位に対する基本的な考え方としては、優先度 100 でジオメトリを設定し、優先度 200 で初期のフラグメントカラー(gl_FragColor)を決定し、より高い番号の優先度ではその色を変更するエフェクトを適用できます。

こちらはレンダリングに使用される各モデルにグラデーションを適用するカスタムシェーダーパーツの例です。

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 を使用して適用できます。

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

前述したように、example.gradient シェーダの gradient_done 変数は、同じリストから適用される他のすべてのシェーダからアクセス可能になります。これは、あるシェーダシステムにオプションのパーツがある場合に便利ですが、独立した2つのシェーダを使用する場合に名前の衝突を引き起こす可能性もあります。

カスタムシェーダーのデバッグに役立つ変数があります。 :

define config.log_gl_shaders = False link

True なら GLSL シェーダープログラム用のソースコードが起動時に log.txt に書き加えられます。

Transform とモデルベースのレンダラリング link

モデルベースのレンダリングは次のプロパティーを ATLと Transform() に追加します :

mesh link
Type:

None or True or tuple

Default:

None

None でなければ、この Transform はモデルとしてレンダリングされます。 つまり :

  • メッシュが作成されます。これが 2 要素のタプルなら、 x 方向と y 方向のメッシュ内のポイント数として取得されます(各次元で少なくとも 2 でなければいけません)。 True の場合、そのメッシュは子から取得されます。

  • この transform の子はテクスチャにレンダリングされます。

  • renpy.texture シェーダーが追加されます。

mesh_pad link
Type:

None or tuple

Default:

None

None でない場合、これは 2 成分または 4 成分のタプルにです。 mesh が True でこれが与えられた場合、これはメッシュで使用されるテクスチャに適用されるテクスチャのサイズにパディングを適用します。 2 成分ののタプルは右と下にパディングを適用し、4成分のタプルは左、上、右、下にパディングを適用します。

gl_pixel_perfect プロパティーと組み合わせるとメッシュにテキストをレンダリングできます。 Ren'Py においてテキストは画面の解像度で描画されるため、メッシュに適用されるテクスチャの境界を越える可能性があります。数ピクセルのパディングを追加すると、テクスチャはより大きくなり、すべてのピクセルが表示されるようになります。例

transform adjust_text:
    mesh True
    mesh_pad (10, 0)
    gl_pixel_perfect True
    shader "shaders.adjust_text"

上記はそのシェーダーに渡されるテクスチャに、そのテキストのすべてのピクセルを含むことを保証します。

shader link
Type:

None or str or list of str

Default:

None

None またはこのレンダーを通して到達するモデル、 ( モデルが作成されるなら ) このレンダーに適用されるシェーダーパーツ名、シェーダーパーツ名のリストです。

blend link
Type:

None or str

Default:

None

None または文字列です。この文字列が config.gl_blend_func で検索され、gl_blend_func プロパティーの値を取得します。ブレンドモードの変更に使用されます。

サポートしているデフォルトのブレンドモードは "normal", "add", "multiply", "min", and "max" です(それぞれ通常、加算、乗算、比較(暗), 比較(明) の合成モードに相当します)。

加えて、 u_renpy でない u_ で始まる uniform は Transform プロパティーとして利用できます。 GL プロパティー は gl_ で始めると Transformプロパティとして利用できるようになります。例えば color_mask プロパティは gl_color_mask として利用可能です。

Blend 関数 link

define config.gl_blend_func = { ... } link

ブレンドモード名をブレンド関数に対応付ける辞書です。ブレンドモードは、後述する blend_func プロパティに提供されます。

デフォルトのブレンドモードです

gl_blend_func["normal"] = (GL_FUNC_ADD, GL_ONE, GL_ONE_MINUS_SRC_ALPHA, GL_FUNC_ADD, GL_ONE, GL_ONE_MINUS_SRC_ALPHA)
gl_blend_func["add"] = (GL_FUNC_ADD, GL_ONE, GL_ONE, GL_FUNC_ADD, GL_ZERO, GL_ONE)
gl_blend_func["multiply"] = (GL_FUNC_ADD, GL_DST_COLOR, GL_ONE_MINUS_SRC_ALPHA, GL_FUNC_ADD, GL_ZERO, GL_ONE)
gl_blend_func["min"] = (GL_MIN, GL_ONE, GL_ONE, GL_MIN, GL_ONE, GL_ONE)
gl_blend_func["max"] = (GL_MAX, GL_ONE, GL_ONE, GL_MAX, GL_ONE, GL_ONE)

Uniforms と attribute link

次の uniform はすべてのモデルで利用可能です。

vec2 u_model_size

モデルの幅と高さ

float u_lod_bias

テクスチャ参照に適用される詳細バイアスのレベルです。これは Transform で設定されるかもしれません。デフォルト値は config.gl_lod_bias から取得され、デフォルトでは -0.5 です。この値は Ren'Py が常に次の大きなレベルを選択して、それをスケールダウンするようにバイアスをかけます。

mat4 u_transform

仮想ピクセルを OpenGL ビューポートに投影するのに使用される transform です。

float u_time

そのフレームの時間です。エポックは未定義なので秒ごとに増える数値として扱うとよいです。この時間は 86400 の剰余なので、一日ごとに 0.0 にリセットされます。

vec4 u_random

フレームごとに (非常に高い確率で) 異なる 0.0 から 1.0 の間の 4 つの乱数です。

vec4 u_viewport

これは現在内部に描画が行われている viewport を指定します。 u_viewport.xy は ウィンドウの左下隅を基準にした viewport の左下隅の座標です。 u_viewport.pq はその viewport の幅と高さを表します。

sampler2D tex0, sampler2D tex1, sampler2D tex2

テクスチャが利用可能なら、対応するサンプラーがこの変数に格納されます。

vec2 res0, vec2 res1, vec2 res2

テクスチャが利用可能なら、そのテクスチャのサイズがこれらの変数に格納されます。テクスチャがディスクから読み込まれたときはこれは画像ファイルのサイズで、テクスチャにレンダリングされた後はレンダリングされたテクスチャ上で描画されるピクセルの数です。

次の attribute はすべてのモデルで利用可能です :

vec4 a_position

レンダリングされた頂点の位置

テクスチャが利用可能なら、次の attribute も使用可能です :

vec2 a_tex_coord

この頂点を投影するテクスチャ内部の座標です。

GL プロパティー link

GLプロパティーは、OpenGLやモデルベースのレンダラのグローバルな状態を変更します。これらのプロパティは Transform や Render.add_property() 関数で使用できます。

gl_blend_func

あればこれは6要素のタプルが期待され、すでに描画されているピクセルと描画するピクセルを合成する方程式と、その方程式のパラメータを設定するために使用されます。

具体的にはこれは (rgb_equation, src_rgb, dst_rgb, alpha_equation, src_alpha, dst_alpha) です。これらは次の呼び出しで使用されます。

glBlendEquationSeparate(rgb_equation, alpha_equation)
glBlendFuncSeparate(src_rgb, dst_rgb, src_alpha, dst_alpha)

これらの関数が何をしているかは OpenGLのドキュメントを参照してください。OpenGL 定数は renpy.uguu からインポートできます。

init python:
    from renpy.uguu import GL_ONE, GL_ONE_MINUS_SRC_ALPHA

一般的に blend transform プロパティーがこれを使用する簡単な方法です。

gl_color_mask

これには、ピクセルの4つのチャンネル(赤、緑、青、アルファ)に対応する真偽値の4タプルが期待されます。あるチャンネルが True であれば、描画処理でそのピクセルに書き込みます。そうでなければ、描画は行われません。

gl_depth

True の場合、 深度バッファをクリアし、この Displayable とこの Displayable の子に対して z バッファ法でのレンダリングを有効にします。

透明なピクセルであっても、任意のピクセルを描画すると、深度バッファが更新されることに注意してください。そのため透明度のある画像に使用すると、予期せぬ問題が発生する可能性があります( 別の方法として show ステートメントの zorderbehind 節を検討してください)。

gl_pixel_perfect

True のとき、Ren'Py はメッシュの最初の頂点が画面上のピクセルと一致するように移動します。これは主にテキストと組み合わせて、テキストがシャープに保たれるようにするために使用されます。

次のプロパティーは、 mesh が設定された Transform または Model() によってテクスチャが作成されるときのみ、プロパティメソッドに渡され効果を持ちます。

gl_drawable_resolution

True または設定されていない場合、テクスチャーはウィンドウがゲームを表示しているのと同じ解像度でレンダリングされます。 False ならその Displayable の仮想解像度でレンダリングされます。

gl_anisotropic

与えられた場合、これはメッシュに渡されるテクスチャが異方性で作成されてるかどうかを判断します。異方性とは、テクスチャーが X と Y で異なる量だけズームされたときに、複数のテクセル(テクスチャピクセル)がサンプリングされる機能です。

これはデフォルトでは True です。 Ren'Py は Pixellate のような特定のエフェクトのためにこれを False に設定します。

gl_mipmap

与えられた場合、これはメッシュに渡されるテクスチャがミップマップで作成されるかどうかを決定します。デフォルトは True です。

gl_texture_wrap

与えられた場合、これはメッシュに適用されるテクスチャがどのようにラップされるかを決定します。これには2要素のタプルが期待され、最初の要素は GL_TEXTURE_WRAP_S を、 2番目の要素は GL_TEXTURE_WRAP_T を設定するために用いられます。これらは通常、作成されたテクスチャの X 軸と Y 軸を表します。

値は OpenGL に含まれ、 renpy.uguu からインポートされます。

init python:
    from renpy.uguu import GL_CLAMP_TO_EDGE, GL_MIRRORED_REPEAT, GL_REPEAT

モデル Displayable link

モデル Displayable はモデルベースのレンダラーで使用するためのモデルを作成するのに役立ちます。

class Model(size=None, **properties) link

これは Ren'Py にモデルベースのレンダラーで使用する 2D や 3D のモデルを作成させる Displayable であり、ここで指定したシェーダーを使用して単一の処理により、または囲んでいるTransform や Displayable によって選択されて描画されます。

size

None でなければ幅と高さのタプルで、そのモデルのサイズを指定するのに使用されます。指定されないと、そのモデルは与えられた領域のサイズになります。テクスチャへの fit パラメータがより優先されます。

mesh メソッドが呼び出されない場合、少なくとも1つのテクスチャを与えられれば Ren'Py がテクスチャをロードする方法に合わせて a_position と a_tex_coord を設定するメッシュが作成され、そうでなければ a_position のみを設定するメッシュが使用されます。

このクラスのすべてのメソッドはそのメソッドが呼び出された Displayable を返すのでチェーン呼び出しが出来ます。

child(displayable, fit=False) link

これは focusmain パラメーターが True に設定される他は texture メソッドと同じです。

grid_mesh(width, height) link

width x height の等間隔のポイントを持つグリッドで構成されるメッシュを作成し、各ポイントを垂直および水平方向の最も近いポイントに接続し、作成されたグリッド内の各長方形を三角形に分割します。

width, height

水平、垂直方法のポイント数で、少なくとも2以上の整数です。

property(name, value) link

gl プロパティーの値を設定します。

name

GL プロパティーの名前を指定する文字列で、 "gl_" 接頭辞を含みます。

value

gl プロパティーの値

shader(shader) link

このモデルにシェーダーを追加します。

shader

このモデルで使用するシェーダーの名前の文字列です。

texture(displayable, focus=False, main=False, fit=False) link

指定の Displayable をレンダリングしてこのモデルにテクスチャを追加します。追加される最初のテクスチャは tex0 で、 2つ目は tex1 と続きます。

focus

True なら、フォーカスイベントがその Displayable に渡されます。ここではそのモデルに対する相対座標がその Displayable に帯する相対座標と 1:1 で対応すると想定しています。

main

True なら、これは Displayable インスペクターに検知されるこの Displayable のメインの子としてマークされます。

fit

True なら、モデルにはその Displayable のサイズが指定されます。これは1つのテクスチャに対してのみ True でしょう。

uniform(name, value) link

シェーダーに渡される uniform の値を設定します。

name

uniform の名前の文字列で、 "u_" を接頭辞に持ちます。

value

uniform の値です。浮動小数、浮動小数の2, 3, 4要素のタプルまたはマトリックスです。

モデル Displayable 例 link

このモデル Displayable は、ATL transform と組み込みのシェーダを組み合わせてディゾルブ transform 作成に使用できます。

transform dt(delay=1.0, new_widget=None, old_widget=None):
    delay delay
    Model().texture(old_widget).child(new_widget)
    shader [ 'renpy.dissolve' ]

    u_renpy_dissolve 0.0
    linear delay u_renpy_dissolve 1.0

モデル Displayable を Displayable の子に使用すると 2つ共が Ren'Py 内にモデルを作成するので、 mesh と互換性がなくなります。

アニメーションシェーダー link

u_time に依存してアニメーションするシェーダーを使用するとき、画面のすべてのシェーダーが表示されるすべてのフレームで実行されてさえ、 Ren'Py が一定の FPS では動作せず、再描画する displayable がなければ、5 FPS の最小フレームレートに落ち込むことに気をつけてください。

ATL transform でアニメーションシェーダーを使用するとき、このことがシェーダーにカクツキを起こさせたり、使用している transform が他に再描画を起こさせない場合、画面の他のオブジェクトがアニメーションする間だけ正常にアニメーションさせたりするかもしれません。この場合は空の ATL ループを加えて再描画の実行を強制できます。

transform fancy_shader:
    shader 'my_fancy_shader'
    pause 0
    repeat

pause 0 はそのフレームを可能な限り早く繰り返します。 pausepause 1.0/30 のような異なる値を設定して、最終フレームレートの指定もできます。

デフォルトのシェーダーパーツ link

renpy.geometry (priority 100) link

Variables:

uniform mat4 u_transform;
attribute vec4 a_position;

Vertex shader:

gl_Position = u_transform * a_position;

renpy.alpha_mask (priority 200) link

Variables:

uniform sampler2D tex0;
uniform sampler2D tex1;
attribute vec2 a_tex_coord;
varying vec2 v_tex_coord;

Vertex shader:

v_tex_coord = a_tex_coord;

Fragment shader:

vec4 src  = texture2D(tex0, v_tex_coord.xy);
vec4 mask = texture2D(tex1, v_tex_coord.xy);

gl_FragColor = vec4(src.r * mask.r, src.g * mask.r, src.b * mask.r, mask.r);

renpy.blur (priority 200) link

Variables:

uniform sampler2D tex0;
attribute vec2 a_tex_coord;
varying vec2 v_tex_coord;
uniform float u_renpy_blur_log2;

Vertex shader:

v_tex_coord = a_tex_coord;

Fragment shader:

gl_FragColor = vec4(0.);
float renpy_blur_norm = 0.;

for (float i = -5.; i < 1.; i += 1.) {
    float renpy_blur_weight = exp(-0.5 * pow(u_renpy_blur_log2 - i, 2.));
    renpy_blur_norm += renpy_blur_weight;
}

gl_FragColor += renpy_blur_norm * texture2D(tex0, v_tex_coord.xy, 0.);

for (float i = 1.; i < 14.; i += 1.) {

    if (i >= u_renpy_blur_log2 + 5.) {
        break;
    }

    float renpy_blur_weight = exp(-0.5 * pow(u_renpy_blur_log2 - i, 2.));
    gl_FragColor += renpy_blur_weight * texture2D(tex0, v_tex_coord.xy, i);
    renpy_blur_norm += renpy_blur_weight;
}

if (renpy_blur_norm > 0.0) {
    gl_FragColor /= renpy_blur_norm;
} else {
    gl_FragColor = texture2D(tex0, v_tex_coord.xy, 0.0);
}

renpy.dissolve (priority 200) link

Variables:

uniform float u_lod_bias;
uniform sampler2D tex0;
uniform sampler2D tex1;
uniform float u_renpy_dissolve;
attribute vec2 a_tex_coord;
varying vec2 v_tex_coord;

Vertex shader:

v_tex_coord = a_tex_coord;

Fragment shader:

vec4 color0 = texture2D(tex0, v_tex_coord.st, u_lod_bias);
vec4 color1 = texture2D(tex1, v_tex_coord.st, u_lod_bias);

gl_FragColor = mix(color0, color1, u_renpy_dissolve);

renpy.imagedissolve (priority 200) link

Variables:

uniform float u_lod_bias;
uniform sampler2D tex0;
uniform sampler2D tex1;
uniform sampler2D tex2;
uniform float u_renpy_dissolve_offset;
uniform float u_renpy_dissolve_multiplier;
attribute vec2 a_tex_coord;
varying vec2 v_tex_coord;

Vertex shader:

v_tex_coord = a_tex_coord;

Fragment shader:

vec4 color0 = texture2D(tex0, v_tex_coord.st, u_lod_bias);
vec4 color1 = texture2D(tex1, v_tex_coord.st, u_lod_bias);
vec4 color2 = texture2D(tex2, v_tex_coord.st, u_lod_bias);

float a = clamp((color0.a + u_renpy_dissolve_offset) * u_renpy_dissolve_multiplier, 0.0, 1.0);
gl_FragColor = mix(color1, color2, a);

renpy.mask (priority 200) link

Variables:

uniform float u_lod_bias;
uniform sampler2D tex0;
uniform sampler2D tex1;
uniform float u_renpy_mask_multiplier;
uniform float u_renpy_mask_offset;
attribute vec2 a_tex_coord;
varying vec2 v_tex_coord;

Vertex shader:

v_tex_coord = a_tex_coord;

Fragment shader:

vec4 src = texture2D(tex0, v_tex_coord.st, u_lod_bias);
vec4 mask = texture2D(tex1, v_tex_coord.st, u_lod_bias);

gl_FragColor = src * (mask.a * u_renpy_mask_multiplier + u_renpy_mask_offset);

renpy.solid (priority 200) link

Variables:

uniform vec4 u_renpy_solid_color;

Fragment shader:

gl_FragColor = u_renpy_solid_color;

renpy.texture (priority 200) link

Variables:

uniform float u_lod_bias;
uniform sampler2D tex0;
attribute vec2 a_tex_coord;
varying vec2 v_tex_coord;

Vertex shader:

v_tex_coord = a_tex_coord;

Fragment shader:

gl_FragColor = texture2D(tex0, v_tex_coord.xy, u_lod_bias);

renpy.matrixcolor (priority 400) link

Variables:

uniform mat4 u_renpy_matrixcolor;

Fragment shader:

gl_FragColor = u_renpy_matrixcolor * gl_FragColor;

renpy.alpha (priority 500) link

Variables:

uniform float u_renpy_alpha;
uniform float u_renpy_over;

Fragment shader:

gl_FragColor = gl_FragColor * vec4(u_renpy_alpha, u_renpy_alpha, u_renpy_alpha, u_renpy_alpha * u_renpy_over);