|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
最近在研究shader,此贴为中间副产品。需Ren'Py 7.4.5以上版本。
此贴中使用的shader代码来源为
ShaderToy-TheUniverseWithin
我只是做了一点修改并移植到Ren'Py上。
首先是主体的shader代码(不要问我是怎么来的,问就是我也不懂):
[RenPy] 纯文本查看 复制代码 init python:
renpy.register_shader("shadertoy.Universewithin", variables="""
uniform float u_time;
uniform vec2 u_model_size
uniform float u_glow;
uniform vec2 u_mouse_pos;
""",fragment_functions="""
float N21(vec2 p)
{
vec3 a = fract(vec3(p.xyx) * vec3(213.897, 653.453, 253.098));
a += dot(a, a.yzx + 79.76);
return fract((a.x + a.y) * a.z);
}
vec2 GetPos(vec2 id, vec2 offs, float t)
{
float n = N21(id+offs);
float n1 = fract(n*10.);
float n2 = fract(n*100.);
float a = t+n;
return offs + vec2(sin(a*n1), cos(a*n2)) * .4;
}
float GetT(vec2 ro, vec2 rd, vec2 p)
{
return dot(p-ro, rd);
}
float LineDist(vec3 a, vec3 b, vec3 p)
{
return length(cross(b-a, p-a)) / length(p-a);
}
float df_line(in vec2 a, in vec2 b, in vec2 p)
{
vec2 pa = p - a, ba = b - a;
float h = clamp(dot(pa,ba) / dot(ba,ba), 0., 1.);
return length(pa - ba * h);
}
float line(vec2 a, vec2 b, vec2 uv)
{
float r1 = .04;
float r2 = .01;
float d = df_line(a, b, uv);
float d2 = length(a-b);
float fade = smoothstep(1.5, .5, d2);
fade += smoothstep(.05, .02, abs(d2-.75));
return smoothstep(r1, r2, d) * fade;
}
float NetLayer(vec2 st, float n, float t)
{
vec2 id = floor(st)+n;
st = fract(st)-.5;
vec2 p[9];
int i=0;
for(float y=-1.; y<=1.; y++)
{
for(float x=-1.; x<=1.; x++) {
p[i++] = GetPos(id, vec2(x,y), t);
}
}
float m = 0.;
float sparkle = 0.;
for(int i=0; i<9; i++)
{
m += line(p[4], p[i], st);
float d = length(st-p[i]);
float s = (.005/(d*d));
s *= smoothstep(1., .7, d);
float pulse = sin((fract(p[i].x) + fract(p[i].y)+t) * 5.) * .4 + .6;
pulse = pow(pulse, 20.);
s *= pulse;
sparkle += s;
}
m += line(p[1], p[3], st);
m += line(p[1], p[5], st);
m += line(p[7], p[5], st);
m += line(p[7], p[3], st);
float sPhase = (sin(t+n) + sin(t*.1)) * .25+ .5;
sPhase += pow(sin(t*.1)*.5 + .5, 50.) * 5.;
m += sparkle * sPhase;
return m;
}
""",
vertex_300="""
v_tex_coord = a_tex_coord;
""",
fragment_300="""
#define NUM_LAYERS 4.
//#define SIMPLE
vec2 uv = (gl_FragCoord.xy - u_model_size.xy*.5) / u_model_size.y;
vec2 M = u_mouse_pos.xy / u_model_size.xy - .5;
float t = u_time * .1;
float s = sin(t);
float c = cos(t);
mat2 rot = mat2(c, -s, s, c);
vec2 st = uv * rot;
M *= rot*2.;
float m = 0.;
for(float i=0.; i<1.; i+=1./NUM_LAYERS)
{
float z = fract(t+i);
float size = mix(15., 1., z);
float fade = smoothstep(0., .6, z) * smoothstep(1., .8, z);
m += fade * NetLayer(st*size-M*z, i, u_time);
}
float glow = u_glow;
vec3 baseCol = vec3(s, cos(t*.4), -sin(t*.24)) * .4 + .6;
vec3 col = baseCol * m;
col += baseCol * glow;
#ifdef SIMPLE
uv *= 10.;
col = vec3(1)*NetLayer(uv, 0., u_time);
uv = fract(uv);
#else
col *= 1.-dot(uv,uv);
t = mod(u_time, 230.);
col *= smoothstep(0., 20., t) * smoothstep(224., 200., t);
#endif
gl_FragColor = vec4(col,1);
""")
然后在自定义可视组件中应用这个shader:
[RenPy] 纯文本查看 复制代码 init python:
class Universewithin(renpy.Displayable):
def __init__(self, child, width, height, glow=0.2, **kwargs):
super(Universewithin, self).__init__(**kwargs)
self.child = renpy.displayable(child)
self.width = width
self.height = height
self.glow = glow
self.mouse_pos = (0, 0)
def render(self, width, height, st, at):
render = renpy.Render(self.width, self.height)
render.place(self.child)
render.add_shader("shadertoy.Universewithin")
render.add_uniform("u_time", st)
render.add_uniform("u_model_size", (self.width, self.height))
render.add_uniform("u_glow", self.glow)
render.add_uniform("u_mouse_pos", self.mouse_pos)
renpy.redraw(self, 0)
return render
def event(self, ev, x, y, st):
self.mouse_pos = (x, self.height - y)
script.rpy中使用图像:
[RenPy] 纯文本查看 复制代码 image universewithin = Universewithin("texture", width = 1280, height = 720)
label main_menu:
return
label start:
show universewithin
pause
整体效果类似于AE中的Plexus粒子插件。
shader中有一个被注释掉的预定义项 SIMPLE ,取消注释后就是简化版,大概能节省一些GPU资源。
CDD中添加了对鼠标事件的处理,画面会模拟镜头移动效果。
|
|