Shader

A place for Ren'Py tutorials and reusable Ren'Py code.
Forum rules
Do not post questions here!

This forum is for example code you want to show other people. Ren'Py questions should be asked in the Ren'Py Questions and Announcements forum.
Post Reply
Message
Author
User avatar
Andredron
Miko-Class Veteran
Posts: 700
Joined: Thu Dec 28, 2017 2:37 pm
Location: Russia
Contact:

Shader

#1 Post by Andredron »

Last edited by Andredron on Wed Jan 24, 2024 12:34 am, edited 5 times in total.

User avatar
Tiger Lyz
Newbie
Posts: 11
Joined: Fri Jan 17, 2020 4:09 am
Projects: Curvy heroine&Virtual Boyfriend, Homunculus, Voice of Paradaise, The Ugly Princess...
Contact:

Re: Shader

#2 Post by Tiger Lyz »

Amazing! Thanks.

User avatar
Andredron
Miko-Class Veteran
Posts: 700
Joined: Thu Dec 28, 2017 2:37 pm
Location: Russia
Contact:

Re: Shader

#3 Post by Andredron »

Ports of several shaders from the site gl-transitions

https://gl-transitions.com/


which, with high python skills, you can upgrade all other shaders and transitions to renpy

Video examples
Attention, this link is a forum for developers of erotic games, and some people from there advertising for adults will not be pleasant

https://f95zone.to/threads/more-transit ... -2.101887/

Download
https://mega.nz/file/WBYVGJpJ#jWPWX9edl ... rGF5IvHRZw

User avatar
Andredron
Miko-Class Veteran
Posts: 700
Joined: Thu Dec 28, 2017 2:37 pm
Location: Russia
Contact:

Re: Shader

#4 Post by Andredron »

Experience modifying the shader on Renpy from a comrade from China birctreel

https://www.renpy.cn/thread-1487-1-1.html

Yesterday, I discussed a lot with Mr. Xizhu about how to apply shaders to layers. When we talked about making more shader programs suitable for renpy, I would like to share my experience on modifying the shader code to adapt to the renpy engine
*Sorry In fact, I don’t know shaders, I don’t know much about renpy, and I don’t even know python (…) The following experience is based on comparing the differences between many shader source codes and renpy versions (and after teacher AxelKong modified my shader code last night). The modification experience may not be correct, but it may work. Please read it with the mentality of following the picture ->
*In addition, the shader source code was searched from the shadertoy website. Many masters have shared their own shaders. Thank you very much. ...!
Shadertoy website address:

https://www.shadertoy.com/

First of all, you need to be familiar with the shader code structure of renpy. Tutorials related to renpy's shader code are here:

https://doc.renpy.cn/zh-CN/model.html#r ... ter_shader

Code: Select all

init python hide.
#shader needs to be defined under this section
    renpy.register_shader("shader.background",
    variables="""
    [Part 1: Variables to use
 
    """,
    fragment_functions="""
   [Part II: Custom Functions Needed to Calculate Screen Effects]
 
    """,
    vertex_100="""
            v_tex_coord = a_tex_coord;
           [actually it should be the third part but I don't really understand what this does, but just keep it that way and don't move this part]
    ""","
 
    fragment_300="""
    [Part III: the custom function of the second part of the above, the introduction of the first part of the variable, applied to the final settlement of the new screen effect step]
    """)
The structure should be much clearer now!


In the first part, you can refer to the renpy page (https://doc.renpy.cn/zh-CN/model.html#r ... ter_shader) to learn the variables that need to be used. These parameters have their own fixed variable types. At the same time, renpy has certain requirements for variable name definition:

The uniform variable must start with u_, the attribute variable must start with a_, and the varying variable must start with v_. Variables starting with u_renpy_, a_renpy and v_renpy are Ren'Py reserved variable names and cannot be used in custom shaders.




This part of the variable definition needs to be placed in the first part of the shader, such as

Code: Select all

uniform float u_time;
uniform vec2 u_model_size;
uniform vec2 res0;
uniform sampler2D tex0;
attribute vec2 a_tex_coord;
varying vec2 v_tex_coord;
Note that our case shader does not actually involve variables such as iTime, but to be on the safe side, you can still define everything that can be defined in the first part

. Understand the meaning of each definable variable, the result I got is that
u_time is the running time of the shader, which generally only appears in some shader effects that change with time. In the Shader source code of the shadertoy station, it is usually defined as iTime
v_tex_coord and The uv height in the shader source code is bound. When you see the definition of uv, you can directly use v_tex_coord
res0, which seems to be each point of the texture and its corresponding position. It is usually written as iResolution in the shader source code. In other words, if you are in the shader source code When you see iResolution.xy, you can change it to res0.xy.
tex0 refers to the input shader screen (= the picture or background texture you want to apply the shader to), which is generally equivalent to iChannel0 in the shader source code
. If iChannel1 appears in the shader source code, Then you need to define a new input shader texture tex1.

Code: Select all

uniform sampler2D tex1
Generally this happens when you want to add a picture filter to the original screen.

The definition names of these variables are different in the shader on the shadertoy page. We will explain how to modify some different variable names below.

================================================== ============

Next, we analyze the basic structure of the shader of the shadertoy station. Each shader on the shadertoy site will be very different according to the author's writing habits, but basically, they are all codes that need to be applied in the second and third parts.
In order to explain how to modify, a shader is selected as an example
https://www.shadertoy.com/view/4tSyzy
would like to thank Mr. luluco250 for the shader
================================== ===================
In the shader example, you can see that the shader source code is divided into two parts:

Code: Select all

const float pi = atan(1.0) * 4.0;
const int samples = 35;
const float sigma = float(samples) * 0.25;
 
float gaussian(vec2 i) {
    return 1.0 / (2.0 * pi * pow2(sigma)) * exp(-((pow2(i.x) + pow2(i.y)) / (2.0 * pow2(sigma))));
}
 
vec3 blur(sampler2D sp, vec2 uv, vec2 scale) {
    vec3 col = vec3(0.0);
    float accum = 0.0;
    float weight;
    vec2 offset;
     
    for (int x = -samples / 2; x < samples / 2; ++x) {
        for (int y = -samples / 2; y < samples / 2; ++y) {
            offset = vec2(x, y);
            weight = gaussian(offset);
            col += texture(sp, uv + scale * offset).rgb * weight;
            accum += weight;
        }
    }
     
    return col / accum;
}
Components starting with const, float, vec3, vec2, etc. are actually calculation functions defined by the shader author (can be understood as a def block in python?). This part will be placed in the shader code of renpy. Part Two
And the following

Code: Select all

void mainImage(out vec4 color, vec2 coord) {
    vec2 ps = vec2(1.0) / iResolution.xy;
    vec2 uv = coord * ps;
     
    color.rgb = blur(iChannel0, uv, ps);
    color.a = 1.0;
}
The part at the beginning of void mainImage refers to the various functions (float, vec2, vec3 blocks) defined above to calculate the final picture effect. In other words, this part will be placed in the third part of the renpy shader.

According to this rule, we can roughly transform the code blocks in the page into the following format

Code: Select all

init python hide.
    renpy.register_shader("shader.sample", # give the shader a random name
    variables="""//This is the part of the code that defines the variables we mentioned first.
        uniform float u_time.
        uniform vec2 u_model_size.
        uniform vec2 res0; uniform sampler2D tex0
        uniform sampler2D tex0; uniform
        attribute vec2 a_tex_coord; varying vec2 v_tex_coord; uniform vec2 v_tex_coord
        varying vec2 v_tex_coord; uniform vec2 v_tex_coord
    """,
    fragment_functions="""//this part of the paste is the definition of several const constants, two float and vec3 format functions gaussian, blur part of the code
    const float pi = atan(1.0) * 4.0;
    const int samples = 35;
    const float sigma = float(samples) * 0.25;
 
    float gaussian(vec2 i) {
        return 1.0 / (2.0 * pi * pow2(sigma)) * exp(-((pow2(i.x) + pow2(i.y)) / (2.0 * pow2(sigma)))).
    }
 
    vec3 blur(sampler2D sp, vec2 uv, vec2 scale) {
        vec3 col = vec3(0.0); vec3 blur(sampler2D sp, vec2 uv, vec2 scale) {
        float accum = 0.0;
        float weight; vec2 offset; vec2 scale
        vec2 offset.
        for (int x = -samples / 2; x < samples / 2; ++x) {
            for (int y = -samples / 2; y < samples / 2; ++y) {
                offset = vec2(x, y); weight = gaussian(offset); ++y) {
                weight = gaussian(offset); col += texture(sp, sp, y); ++y
                
                accum += weight; }
            }
        }
         
        return col / accum; }
    }
     
    """,
    vertex_100="""
            v_tex_coord = a_tex_coord;
    """, v_tex_coord = a_tex_coord; """,
         
    fragment_300=""""// Pay attention! This part of the paste is the code inside the void mainimage, removing the definition header part of the voidimage, only the pure version of the internal code (not the
 
    vec2 ps = vec2(1.0) / iResolution.xy;
    vec2 uv = coord * ps;
    color.rgb = blur(iChannel0, uv, ps);
    color.a = 1.0;
    """)
So, can I run away now?
Obviously not! O-zzzzzzzzzzzz
Because you will find that in the shadertoy shader code, there are some variables that we have never defined, including
iResolution.xy, coord, iChannel0, etc. (and including iTime that does not appear in this shader)
. Some of the variables have been defined in the first part above, and some are built-in to the renpy shader, but their names are different from the shader variables written by everyone on the shadertoy site. Please note that renpy has specially defined names for these variables! So we need to convert the variables of the shadertoy station into variables that renpy can recognize. The following is a corresponding relationship that I have figured out. Some of them have already been mentioned in the first part, so I will list them again here. The left side is the Shader source code, and the right side is the renpy corresponding variable name that should be changed to
iTime -> u_time
iResolution.xy -> res0.xy
texture(...generally iChannel0 will appear in parentheses) -> texture2D(....)
iChannel0 -> tex0
iChannel1 -> tex1

Therefore, you need to change the corresponding variable names in the original shader code to the variable names defined by renpy. The results are as follows:

Code: Select all

init python hide.
    renpy.register_shader("shader.sample",
    variables="""
        uniform float u_time; uniform vec2 u_model_size; uniform
        uniform vec2 u_model_size; uniform vec2 res0; uniform
        uniform vec2 res0; uniform sampler2D tex0
        uniform sampler2D tex0; uniform
        attribute vec2 a_tex_coord; varied vec2 v_tex_coord; varied vec2 v_tex_coord; uniform
        varying vec2 v_tex_coord; uniform vec2 res0; uniform sampler2D tex0; attribute vec2 a_tex_coord
    """,
    fragment_functions="""
    const float pi = atan(1.0) * 4.0;
    const int samples = 35;
    const float sigma = float(samples) * 0.25;
    float gaussian(vec2 i) {
        return 1.0 / (2.0 * pi * pow2(sigma)) * exp(-((pow2(i.x) + pow2(i.y)) / (2.0 * pow2(sigma)))).
    }
 
    vec3 blur(sampler2D sp, vec2 uv, vec2 scale) {
        vec3 col = vec3(0.0); vec3 blur(sampler2D sp, vec2 uv, vec2 scale) {
        float accum = 0.0;
        float weight; vec2 offset; vec2 scale
        vec2 offset.
        for (int x = -samples / 2; x < samples / 2; ++x) {
            for (int y = -samples / 2; y < samples / 2; ++y) {
                offset = vec2(x, y); weight = gaussian(offset); ++y) {
                weight = gaussian(offset).
                col += texture2D(sp, uv + scale * offset).rgb * weight; //note, change texture here to texture2D
                accum += weight; }
            }
        }
         
        return col / accum; }
    }
     
    """,
    vertex_100="""
            v_tex_coord = a_tex_coord;
    """, fragment_300=""
         
    fragment_300="""
 
 
    vec2 ps = vec2(1.0) / res0.xy; // replace iResolution with res0
    vec2 uv = v_tex_coord;//regardless of how it uv is written, defining uv as v_tex_coord is generally fine. In shader source code uv is often defined as fragCoord.xy / iResolution.xy, but if you change it to gl_FragCoord.xy / res0.xy then the image will be inverted ......... ......... don't ask me why I know ..................
    color.rgb = blur(tex0, uv, ps);
    color.a = 1.0;
    """)
So, can this shader be run?
——————————Obviously it still doesn’t work…! ! ! ! ! ! ! Because we did not define color! ! And there are ghost things like pow2...!
(Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa That is so troublesome...!!!!!!)

The following part is not a general tutorial for modifying shader source code, but It’s about the modifications in this example shader (because the shader is written by different authors, the code and variable naming habits will be different, but it can be used as an example to learn from). First of all

, there is no such thing as pow2(XX) in Python. Damn...! After searching around, I found that this is a function in C language that raises 2 to the power of XX. In python, it should be changed to pow(2,XX).

Secondly, compare our modified third part with the void mainimage code in the source code. You will find that the source code defines a variable of type vec4 and name color. The following is the void mainImage in the example.

Code: Select all

void mainImage(out vec4 color, vec2 coord) {
    vec2 ps = vec2(1.0) / iResolution.xy;
    vec2 uv = coord * ps;
     
    color.rgb = blur(iChannel0, uv, ps);
    color.a = 1.0;
}
riends who often modify shaders know (……………………) that this variable actually defines the final picture effect, but writing it like this is not enough. If you want to assign this picture effect to the renpy page, you need to Redefine color in the third module (after all, we deleted the header of void mainimage, there is no place to define color), and then assign it to gl_Fragcolor <- this name refers to the picture that is actually returned after the shader changes it.
for example:

Code: Select all

fragment_300="""
vec2 ps = vec2(1.0) / res0.xy;
vec2 uv = v_tex_coord;
vec4 color; //added this line
color.rgb = blur(tex0, uv, ps);
color.a = 1.0;
gl_Fragcolor = color;// then assign the result of color to the final output parameter gl_Fragcolor
""")

So the final modified shader is:

Code: Select all

init python hide:
    renpy.register_shader("shader.sample",
    variables="""
        uniform float u_time;
        uniform vec2 u_model_size;
        uniform vec2 res0;
        uniform sampler2D tex0;
        attribute vec2 a_tex_coord;
        varying vec2 v_tex_coord;
 
    """,
    fragment_functions="""
    const float pi = atan(1.0) * 4.0;
    const int samples = 35;
    const float sigma = float(samples) * 0.25;
    float gaussian(vec2 i) {
        return 1.0 / (2.0 * pi * pow(2,sigma)) * exp(-((pow(2,i.x) + pow(2,i.y)) / (2.0 * pow(2,sigma))));//注意看,这里的pow2()全部改成了pow(2,xxxx)
    }
 
    vec3 blur(sampler2D sp, vec2 uv, vec2 scale) {
        vec3 col = vec3(0.0);
        float accum = 0.0;
        float weight;
        vec2 offset;
        for (int x = -samples / 2; x < samples / 2; ++x) {
            for (int y = -samples / 2; y < samples / 2; ++y) {
                offset = vec2(x, y);
                weight = gaussian(offset);
                col += texture2D(sp, uv + scale * offset).rgb * weight;
                accum += weight;
            }
        }
         
        return col / accum;
    }
     
    """,
    vertex_100="""
            v_tex_coord = a_tex_coord;
    """,
         
    fragment_300="""
 
    vec2 ps = vec2(1.0) / res0.xy;
    vec2 uv = v_tex_coord;
    vec4 color;
    color.rgb = blur(tex0, uv, ps);
    color.a = 1.0;
    gl_FragColor = color;
    """)
We can define this shader and use it in transform. like

Code: Select all

transform sample(child):# Define a transform effect called sample
    Model().shader("shader.sample").child(child, fit=True)
 
 
 
label start.
  show e001_01 at sample#Apply sample effect to image
  e "See how it works"

User avatar
Andredron
Miko-Class Veteran
Posts: 700
Joined: Thu Dec 28, 2017 2:37 pm
Location: Russia
Contact:

Re: Shader

#5 Post by Andredron »

Post https://www.renpy.cn/thread-1487-1-1.html

1) Watercolor effect

https://www.shadertoy.com/view/slcSRM
he effect refers to the shadertoy website, removed (due to personal needs) White edges, weakened brightening effect, pure watercolor special effect, because it is dynamic, looks more interesting than other watercolor effects
(I finally gave up because I found that the original art style is watercolor and this thing is not suitable!!!)

Code: Select all

renpy.register_shader("shader.watercolor",
variables="""
    uniform float u_time;
    uniform vec2 u_model_size;
    uniform vec2 res0;
    uniform sampler2D tex0;
    attribute vec2 a_tex_coord;
    varying vec2 v_tex_coord;
    uniform vec4 u_color
""",
fragment_functions="""
    #define M_PI 3.14159265358979323846
    vec2 hash( vec2 p ) // replace this by something better
    {
        p = vec2( dot(p,vec2(127.1,311.7)), dot(p,vec2(269.5,183.3)) );
        return -1.0 + 2.0*fract(sin(p)*43758.5453123);
    }
 
    float noise( in vec2 p )
    {
        const float K1 = 0.366025404; // (sqrt(3)-1)/2;
        const float K2 = 0.211324865; // (3-sqrt(3))/6;
 
        vec2  i = floor( p + (p.x+p.y)*K1 );
        vec2  a = p - i + (i.x+i.y)*K2;
        float m = step(a.y,a.x); 
        vec2  o = vec2(m,1.0-m);
        vec2  b = a - o + K2;
        vec2  c = a - 1.0 + 2.0*K2;
        vec3  h = max( 0.5-vec3(dot(a,a), dot(b,b), dot(c,c) ), 0.0 );
        vec3  n = h*h*h*h*vec3( dot(a,hash(i+0.0)), dot(b,hash(i+o)), dot(c,hash(i+1.0)));
        return dot( n, vec3(70.0) );
    }
 
 
    float simp(vec2 uv) {
        uv *= 5.0;
        mat2 m = mat2( 1.6,  1.2, -1.2,  1.6 );
        float f = 0.5000*noise( uv ); uv = m*uv;
        f += 0.2500*noise( uv ); uv = m*uv;
        f += 0.1250*noise( uv ); uv = m*uv;
        f += 0.0625*noise( uv ); uv = m*uv;
        f = 0.2 + 0.8*f;
        return f;
    }
 
 
    vec4 bumpFromDepth(vec2 uv, vec2 resolution, float scale) {
    vec2 step = 1. / resolution;
         
    float height = simp(uv);
         
    vec2 dxy = height - vec2(
        simp(uv + vec2(step.x, 0.)), 
        simp(uv + vec2(0., step.y))
    );
         
    return vec4(normalize(vec3(dxy * scale / step, 1.)), height);
    }
 
 
 
 
    float sdRoundedBox( in vec2 p, in vec2 b, in vec4 r )
    {
        r.xy = (p.x>0.0)?r.xy : r.zw;
        r.x  = (p.y>0.0)?r.x  : r.y;
        vec2 q = abs(p)-b+r.x;
        return min(max(q.x,q.y),0.0) + length(max(q,0.0)) - r.x;
    }
""",
vertex_100="""
        v_tex_coord = a_tex_coord;
""",
     
fragment_300="""
    // Normalized pixel coordinates (from 0 to 1)
    vec2 uv = v_tex_coord;
    vec4 offset = bumpFromDepth(uv + vec2(floor(u_time*4.0)/4.0), res0.xy, .05)/80.0;
     
 
    // Output to screen
                //texture(iChannel0, uv + offset.xy)*0.4;
     
                 
    gl_FragColor = (texture2D(tex0, uv + offset.xy)*0.4) + (texture2D(tex0, uv)*0.6);
    gl_FragColor += length(bumpFromDepth(uv, res0.xy, .1))*0.05;
 
""")
2) Stroke effect

https://www.shadertoy.com/view/DtBBWd

Super easy to use stroke! ! ! ! If you want to modify the thickness of the stroke, modify the [line_thickness] parameter. The default in the original post is 10. I changed it to 3 here, and the effect is already very good.
Note that the stroke thickness value cannot be too large, because this stroke logic actually pastes your original image several times in the four directions of the background. As a result, if the stroke thickness value is too large, ghosting will appear on the stroked edge
* Because I don't need to modify the stroke thickness, I didn't release this variable. If you need to adjust the line width at any time, just declare a new variable at the beginning and assign it to line_thickness

. I changed the shader code here to make it easier to use the shader. You can adjust the stroke color at any time, that is, you just need to modify the four-bit vector value following the u_color parameter.
However, please note that the color writing method of glsl is different from that of renpy. The four-bit vector value is (RR/255, GG/255, BB/255, Transparency), you need to convert the hexadecimal color into RRGGBB and then divide it by 255 to turn it into a decimal.
For example, the color of my stroke is actually the hexadecimal color #C69949
(I used this, it is very easy to use, you can even use it to change the stroke color to create a button floating effect)

Code: Select all

renpy.register_shader("shader.outline",
    variables="""
        uniform float u_time;
        uniform vec2 u_model_size;
        uniform vec2 res0;
        uniform sampler2D tex0;
        attribute vec2 a_tex_coord;
        varying vec2 v_tex_coord;
        uniform vec4 u_color
    """,
    fragment_functions="""
    """,
    vertex_100="""
            v_tex_coord = a_tex_coord;
    """,
         
    fragment_300="""
        vec2 uv = v_tex_coord;
 
        vec2 texture_PIXEL_SIZE = vec2(0.0005, 0.0005);
        float line_thickness = 3;
         
        vec2 size = texture_PIXEL_SIZE * line_thickness;
         
        float outline = texture2D(tex0, uv + vec2(-size.x, 0)).a;
        outline += texture2D(tex0, uv + vec2(0, size.y)).a;
        outline += texture2D(tex0, uv + vec2(size.x, 0)).a;
        outline += texture2D(tex0, uv + vec2(0, -size.y)).a;
        outline += texture2D(tex0, uv + vec2(-size.x, size.y)).a;
        outline += texture2D(tex0, uv + vec2(size.x, size.y)).a;
        outline += texture2D(tex0, uv + vec2(-size.x, -size.y)).a;
        outline += texture2D(tex0, uv + vec2(size.x, -size.y)).a;
        outline = min(outline, 1.0);
         
        vec4 color = texture2D(tex0, uv);
        vec4 COLOR = mix(color, u_color, outline - color.a);
         
        gl_FragColor = COLOR;
    """)
 
#用的时候就写XXX at outline就行
 
transform outline():
    mesh True#这里表示描边仅用在外轮廓上,防止你层叠图它每一层都给你描一次边
    shader 'shader.outline'
    u_color (0.831,0.792,0.808,1)#这里修改描边颜色
3) Fast and good Gaussian blur

https://www.shadertoy.com/view/Xltfzj

By the way, transform gsblur is defined. When using it, just at gsblur (rad value) Just fine, rad is your blur radius. It is recommended not to be larger than 10, otherwise it will be fast but not that good... (sweat)

Code: Select all

renpy.register_shader("shader.gsblur",
variables="""
    uniform float u_radius;
    uniform vec2 u_model_size;
    uniform vec2 res0;
    uniform sampler2D tex0;
    attribute vec2 a_tex_coord;
    varying vec2 v_tex_coord;
""",
fragment_functions="""
""",
vertex_100="""
        v_tex_coord = a_tex_coord;
""",
     
fragment_300="""
    float Pi = 6.28318530718; // Pi*2
    // GAUSSIAN BLUR SETTINGS {{{
    float Directions = 16.0; // BLUR DIRECTIONS (Default 16.0 - More is better but slower)
    float Quality = 6.0; // BLUR QUALITY (Default 4.0 - More is better but slower)
    float Size = u_radius; // BLUR SIZE (Radius)
    // GAUSSIAN BLUR SETTINGS }}}
 
    vec2 Radius = Size/res0.xy;
     
    // Normalized pixel coordinates (from 0 to 1)
    vec2 uv = v_tex_coord;
    // Pixel colour
    vec4 Color = texture2D(tex0, uv);
     
    // Blur calculations
    for( float d=0.0; d<Pi; d+=Pi/Directions)
    {
        for(float i=1.0/Quality; i<=1.0; i+=1.0/Quality)
        {
            Color += texture2D(tex0, uv+vec2(cos(d),sin(d))*Radius*i);      
        }
    }
     
    // Output to screen
    Color /= Quality * Directions - 15.0;
    gl_FragColor =  Color;
""")

User avatar
Andredron
Miko-Class Veteran
Posts: 700
Joined: Thu Dec 28, 2017 2:37 pm
Location: Russia
Contact:

Re: Shader

#6 Post by Andredron »

https://github.com/CrossCouloir/renpy-b ... me-ov-file

Photoshop-style blend mode shaders for Ren'Py.

This library adapts Jamie Owen's glsl-blend library to be used as Ren'Py shaders, allowing you to apply Photoshop-style image blending via a Ren'Py transform.

Installation
This project consists of a series of .rpy files. This means the best way to include it into your Ren'Py project is to download the files and place them into your game directory. You do not need to include the files for any shaders you don't plan to use, however you must include base.rpy.

To download an archive of this project, click the green Code button on GitHub and select "Download ZIP".

Prerequisites
You must have a version of Ren'Py which supports model-based rendering.

Blend modes
A few additional simple blend modes have been added to the config.gl_blend_func dictionary. If you add the appropriate source files to your project, you'll be able to use any of these blend functions with the blend transform property. The following blend modes have been added in this way:

Code: Select all

add
linear_dodge (synonym for add)
lighten
darken
Blend shaders
More complex blend modes are implemented as GLSL shaders that will blend a texture image onto a base image using the specified blend mode. The easiest way to include any of these shaders is to use one of the included shader functions packaged with this library. Each shader function has the name cc_<blend_mode_name> (for example, cc_screen or cc_soft_light). They take the following arguments:

:

base (Displayable): the base displayable, onto which other image data will be blended.
tex (Displayable): the texture displayable, which will be blended onto the base displayable in the specified mode.
fit (boolean, default True): if True, tex will be resized to be the same size as base. Weird stuff may happen if you pass False.
Here is an example of how shaders are used in transforms:

Code: Select all

transform my_special_lighting(child=None):
  cc_soft_light(child, Solid("#ffffff7f"))
This transform applies a partially transparent pure white using the cc_soft_light displayable. Note that the transform takes the child=None argument: for the transform to work correctly, you must include this argument. Ren'Py will correctly set the value of child to be the base displayable the transform is applying to. cc_soft_light, and the other blend mode functions, return a displayable which will be the child displayable of your transform.

Once you've created the transform, you can use it the same way you'd use any other transform.

show protagonist_sprite at center, my_special_lighting
The following shaders are currently available:

Code: Select all

cc_color_burn
cc_color_dodge
cc_difference
cc_exclusion
cc_linear_burn
cc_overlay
cc_screen
cc_soft_light
cc_vivid_light
Limitations
Animating between the blend modes is not supported. You may get wacky results, or it may cause crashes, or nothing may happen. Shader-based transforms may not work with layered images.

Contributing
This project accepts pull requests. Please create a pull request if you would like to contribute. If you have any feature requests, please create a project issue and I will address it as soon as I can.

License
This project is made available under the MIT license. Please see LICENSE.md for more information.

Post Reply

Who is online

Users browsing this forum: No registered users