RenPy中文空间

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 60|回复: 0

[原创] 使用shader绘制宇宙星空

[复制链接]
发表于 7 天前 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
本帖最后由 被诅咒的章鱼 于 2021-7-23 16:36 编辑

最近在研究shader,此贴为中间副产品。需Ren'Py 7.4.5以上版本。

此贴中使用的shader代码来源为
ShaderToy-StarNest

我只是做了一点修改和移植到Ren'Py上。

首先是主体的shader代码(不要问我是怎么来的,问就是我也不懂):
[RenPy] 纯文本查看 复制代码
init python:

    renpy.register_shader("shadertoy.StarNest", variables="""
        uniform float u_time;
        uniform vec2 u_model_size;
    """,fragment_functions="""
        vec2 MatMultiplayVec(vec4 m, vec2 v)
        {
            return vec2(m.x * v.x + m.z * v.y, m.y * v.x + m.w * v.y);
        }
        float SCurve (float value)
        {
            if(value < 0.5)
            {
                return value * value * value * value * value * 16.0; 
            }
            value -= 1.0;
            return value * value * value * value * value * 16.0 + 1.0;
        }
    """,vertex_300="""
        v_tex_coord = vec2(a_tex_coord.s, 1.0 - a_tex_coord.t);
    """,
    
        fragment_300="""
        #define iterations 17
        #define formuparam 0.53

        #define volsteps 20
        #define stepsize 0.1

        #define zoom   0.800
        #define tile   0.850
        #define speed  0.002 

        #define brightness 0.002
        #define darkmatter 0.300
        #define distfading 0.750
        #define saturation 0.750

        vec2 uv=v_tex_coord-.5;
        uv.y*=u_model_size.y/u_model_size.x;
        vec3 dir=vec3(uv*zoom,1.);
        float time=u_time*speed+.25;

        vec3 from=vec3(1.,.5,0.5);
        from+=vec3(time*2.,time,-2.);

        float s=0.1,fade=1.;
        vec3 v=vec3(0.);
        for (int r=0; r<volsteps; r++)
        {
            vec3 p=from+s*dir*.5;
            p = abs(vec3(tile)-mod(p,vec3(tile*2.)));
            float pa,a=pa=0.;
            for (int i=0; i<iterations; i++)
            { 
                p=abs(p)/dot(p,p)-formuparam;
                a+=abs(length(p)-pa);
                pa=length(p);
            }
            float dm=max(0.,darkmatter-a*a*.001);
            a = pow(a, 2.5);
            if (r>6) fade*=1.-dm;
            v+=fade;
            v+=vec3(s,s*s,s*s*s*s)*a*brightness*fade;
            fade*=distfading;
            s+=stepsize;
        }

        v=mix(vec3(length(v)),v,saturation);

        vec4 C = vec4(v*.01,1.);
        C.r = pow(C.r, 0.35);
        C.g = pow(C.g, 0.36);
        C.b = pow(C.b, 0.4);

        vec4 L = C;
        C.r = mix(L.r, SCurve(C.r), 1.0);
        C.g = mix(L.g, SCurve(C.g), 0.9);
        C.b = mix(L.b, SCurve(C.b), 0.6);

        gl_FragColor = C;
    """)


然后是在自定义可视组件中应用这个shader:
[RenPy] 纯文本查看 复制代码
init python:

    class StarNest(renpy.Displayable):

        def __init__(self, child, width, height, **kwargs):
            super(StarNest, self).__init__(**kwargs)
            
            self.child = renpy.displayable(child)
            self.width = width
            self.height = height

        def render(self, width, height, st, at):
            render = renpy.Render(self.width, self.height)
            render.place(self.child)
            render.add_shader("shadertoy.StarNest")
            render.add_uniform("u_time", st)
            render.add_uniform("u_model_size", (self.width, self.height))
            renpy.redraw(self, 0)
            return render


script.rpy中使用图像:
[RenPy] 纯文本查看 复制代码
image starnest = StarNest("texture", width = 1280, height = 720)

label main_menu:
    return

label start:

    show starnest
    
    pause

注意这里使用一张名为“texture”的图片,图片内容是什么不重要,尺寸需要为1280×720(或者根据需求修改)。
shader中几个预编译的值都可以修改。(我就是不做成从类的构造函数传入参数)
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|RenPy中文空间 ( 苏ICP备17067825号 | 苏公网安备 32092302000068号 )

GMT+8, 2021-7-29 13:11 , Processed in 0.043193 second(s), 11 queries , File On.

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表