기본 셰이더 파트

셰이더 파트는 모델 기반 렌더링과 텍스트 셰이더에서 사용합니다. 이 페이지에는 우선순위별 파트 색인과 각 셰이더 파트의 소스 코드가 있습니다.

정점 셰이더 파트의 우선순위

Ren'Py는 정점 셰이더 파트의 우선순위를 다음과 같이 사용합니다.

  • 우선순위 0: gl_Position을 설정합니다.

  • 우선순위 10: 조정 전의 gl_Position을 가상 좌표나 그리기 좌표로 저장합니다.

  • 우선순위 20~80: 가상 좌표나 그리기 좌표에서 gl_Position을 조정합니다.

  • 우선순위 90: 조정 후의 gl_Position을 가상 좌표나 그리기 좌표로 저장합니다.

  • 우선순위 100: gl_Position을 뷰포트 좌표로 변환합니다.

  • 우선순위 200: gl_Position을 건드리지 않고 varying 변수에 추가 정보를 저장합니다.

실행 순서는 다음과 같습니다.

프래그먼트 셰이더 파트의 우선순위

Ren'Py는 프래그먼트 셰이더 파트의 우선순위를 다음과 같이 사용합니다.

  • 우선순위 200: 원래 색상을 결정해 gl_FragColor에 저장합니다.

  • 우선순위 300: 해당 색상에 두 번째 텍스처를 곱합니다.

  • 우선순위 325: 텍스트 셰이더가 알파를 조정하기 전에 원래 알파를 저장합니다.

  • 우선순위 350: 알파를 조정하는 텍스트 셰이더를 적용합니다.

  • 우선순위 375: 해당 텍스트 셰이더의 효과 일부를 되돌릴 수 있습니다.

  • 우선순위 400: Transform과 디스플레이어블에 따른 변경을 적용해 색상을 조정합니다.

  • 우선순위 500: Transform과 디스플레이어블에 따른 변경을 적용해 알파 채널을 조정합니다.

실행 순서는 다음과 같습니다.

renpy.alpha

변수:

uniform float u_renpy_alpha;
uniform float u_renpy_over;

프래그먼트 셰이더 (우선순위 500):

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

renpy.alpha_mask

변수:

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

정점 셰이더 (우선순위 200):

v_tex_coord = a_tex_coord;

프래그먼트 셰이더 (우선순위 500):

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

변수:

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

정점 셰이더 (우선순위 200):

v_tex_coord = a_tex_coord;

프래그먼트 셰이더 (우선순위 200):

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

변수:

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;

정점 셰이더 (우선순위 200):

v_tex_coord = a_tex_coord;

프래그먼트 셰이더 (우선순위 200):

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.geometry

변수:

uniform mat4 u_transform;
attribute vec4 a_position;

정점 셰이더 (우선순위 0):

gl_Position = a_position;

정점 셰이더 (우선순위 100):

gl_Position = u_transform * gl_Position;

renpy.imagedissolve

변수:

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;

정점 셰이더 (우선순위 200):

v_tex_coord = a_tex_coord;

프래그먼트 셰이더 (우선순위 200):

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

변수:

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;

정점 셰이더 (우선순위 200):

v_tex_coord = a_tex_coord;

프래그먼트 셰이더 (우선순위 200):

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.matrixcolor

변수:

uniform mat4 u_renpy_matrixcolor;

프래그먼트 셰이더 (우선순위 400):

gl_FragColor = u_renpy_matrixcolor * gl_FragColor;

renpy.solid

변수:

uniform vec4 u_renpy_solid_color;

프래그먼트 셰이더 (우선순위 200):

gl_FragColor = u_renpy_solid_color;

renpy.texture

변수:

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

정점 셰이더 (우선순위 200):

v_tex_coord = a_tex_coord;

프래그먼트 셰이더 (우선순위 200):

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

textshader.dissolve

변수:

uniform float u_textshader_dissolve_duration;
uniform float u_text_slow_duration;
uniform float u_text_slow_time;
attribute float a_text_time;
varying float v_text_time;

정점 셰이더 (우선순위 200):

v_text_time = a_text_time;

프래그먼트 셰이더 (우선순위 350):

float l_textshader_dissolve_duration = u_textshader_dissolve_duration * u_text_slow_duration;
float l_textshader_dissolve_done;
if (l_textshader_dissolve_duration > 0.0) {
    l_textshader_dissolve_done = clamp((u_text_slow_time - v_text_time) / l_textshader_dissolve_duration, 0.0, 1.0);
} else {
    l_textshader_dissolve_done = v_text_time <= u_text_slow_time ? 1.0 : 0.0;
}
gl_FragColor = gl_FragColor * l_textshader_dissolve_done;

textshader.flip

변수:

uniform float u_textshader_flip_duration;
uniform float u_text_slow_duration;
uniform float u_text_slow_time;
attribute vec2 a_text_center;
attribute float a_text_min_time;

정점 셰이더 (우선순위 20):

float l_textshader_flip_duration = u_textshader_flip_duration * u_text_slow_duration;
float l_textshader_flip_done;

if (l_textshader_flip_duration > 0.0) {
    l_textshader_flip_done = clamp((u_text_slow_time - a_text_min_time) / l_textshader_flip_duration, 0.0, 1.0);
} else {
    l_textshader_flip_done = a_text_min_time <= u_text_slow_time ? 1.0 : 0.0;
}

gl_Position.x = mix(a_text_center.x - (gl_Position.x - a_text_center.x), gl_Position.x, l_textshader_flip_done);

textshader.jitter

변수:

uniform vec2 u_textshader_jitter_jitter;
uniform vec4 u_random;
uniform float u_text_to_drawable;

정점 셰이더 (우선순위 30):

vec2 l_textshader_jitter_jitter = u_textshader_jitter_jitter * u_text_to_drawable;
gl_Position.xy += l_textshader_jitter_jitter * u_random.xy - l_textshader_jitter_jitter / 2.0;

textshader.linetexture

변수:

uniform sampler2D u_textshader_linetexture_texture;
uniform vec2 u_textshader_linetexture_scale;
uniform vec2 u_textshader_linetexture_texture_res;

uniform float u_text_to_virtual;
uniform float u_text_main;

attribute vec2 a_text_center;
varying vec2 v_textshader_linetexture_coord;

정점 셰이더 (우선순위 10):

v_textshader_linetexture_coord = vec2( gl_Position.x, (gl_Position.y - a_text_center.y)) / u_textshader_linetexture_scale * u_text_to_virtual / u_textshader_linetexture_texture_res;
v_textshader_linetexture_coord.y += 0.5;

프래그먼트 셰이더 (우선순위 300):

if (u_text_main == 1.0) {
    gl_FragColor = texture2D(u_textshader_linetexture_texture, v_textshader_linetexture_coord) * gl_FragColor;
}

textshader.offset

변수:

uniform vec2 u_textshader_offset_offset;
uniform float u_text_to_drawable;

정점 셰이더 (우선순위 35):

gl_Position.xy += u_textshader_offset_offset * u_text_to_drawable;

textshader.slowalpha

변수:

uniform float u_textshader_slowalpha_alpha

프래그먼트 셰이더 (우선순위 325):

vec4 l_textshader_slowalpha_color = gl_FragColor;

프래그먼트 셰이더 (우선순위 375):

gl_FragColor = mix(gl_FragColor, l_textshader_slowalpha_color, u_textshader_slowalpha_alpha);

textshader.texture

변수:

uniform sampler2D u_textshader_texture_texture;
uniform vec2 u_textshader_texture_texture_res;

uniform float u_text_to_virtual;
uniform float u_text_main;
varying vec2 v_textshader_texture_coord;

정점 셰이더 (우선순위 10):

v_textshader_texture_coord = u_text_to_virtual * gl_Position.xy / u_textshader_texture_texture_res;

프래그먼트 셰이더 (우선순위 300):

if (u_text_main == 1.0) {
    gl_FragColor = texture2D(u_textshader_texture_texture, v_textshader_texture_coord) * gl_FragColor;
}

textshader.typewriter

변수:

uniform float u_text_slow_time;
attribute float a_text_min_time;
varying float v_text_min_time;

정점 셰이더 (우선순위 200):

v_text_min_time = a_text_min_time;

프래그먼트 셰이더 (우선순위 350):

float l_textshader_typewriter_done = v_text_min_time <= u_text_slow_time ? 1.0 : 0.0;
gl_FragColor = gl_FragColor * l_textshader_typewriter_done;

textshader.wave

변수:

uniform float u_textshader_wave_amplitude;
uniform float u_textshader_wave_frequency
uniform float u_textshader_wave_wavelength;

uniform float u_time;
uniform float u_text_to_drawable;
attribute float a_text_index;

정점 셰이더 (우선순위 40):

gl_Position.y += cos(2.0 * 3.14159265359 * (a_text_index / u_textshader_wave_wavelength + u_time * u_textshader_wave_frequency)) * u_textshader_wave_amplitude * u_text_to_drawable;

textshader.zoom

변수:

uniform float u_textshader_zoom_zoom;
uniform float u_textshader_zoom_duration;
uniform float u_text_slow_duration;
uniform float u_text_slow_time;
attribute vec2 a_text_center;
attribute float a_text_min_time;

정점 셰이더 (우선순위 25):

float l_textshader_zoom_duration = u_textshader_zoom_duration * u_text_slow_duration;

if (l_textshader_zoom_duration > 0.0) {
    float l_textshader_zoom_done = clamp((u_text_slow_time - a_text_min_time) / l_textshader_zoom_duration, 0.0, 1.0);
    gl_Position.xy = mix(a_text_center + (gl_Position.xy - a_text_center) * u_textshader_zoom_zoom, gl_Position.xy, l_textshader_zoom_done);
}