马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
本帖最后由 Maz马 于 2026-5-2 20:58 编辑
写了一个类3D正倾斜效果的transform
预览
变换组件
鼠标视差
3D 倾斜
边缘渐变
效果类似于3D舞台中的RotateMatrix(),即绕着某一轴做3d旋转
但是应用了3d舞台后的一些组件会失去交互功能,例如按钮(原理暂时不明,我对3d舞台没有过多了解)
因为这个原因使用Shader来进行模仿
因为透视形变是UI,UX美术中非常泛用的功能,却没有看人做过
更多的替代方案是直接photoshop启动,输出具有透视的图片
用了shader之后就可以应用在screen下的容器,按钮,并维持交互
但是本质上是shader,所以按钮的矩形交互区域尺寸并没有实际改变,只是视觉欺骗
如果需求十分严谨的话也可以使用按钮自带的focus_mask特性callable来计算(未尝试)
[RenPy] 纯文本查看 复制代码 init python:
# 3D倾斜
renpy.register_shader("Maz.Side3D",
variables = """
uniform sampler2D tex0;
uniform float u_s3d_t;
uniform float u_s3d_d;
uniform float u_s3d_s;
attribute vec2 a_tex_coord;
varying vec2 v_tex_coord;
""",
vertex_300="""
v_tex_coord = a_tex_coord;
""",
fragment_300="""
vec2 uv = v_tex_coord;
vec2 final_uv = uv;
float depth = max(u_s3d_d,0.001);
//不允许向外倾斜,向外倾斜应该使用对边,否则内容会被裁切
float tilt = max(u_s3d_t,0.0);
if (u_s3d_s == 1.0) {
float slope = 1.0 - tilt * uv.x;
float tilted_y = (uv.y - 0.5) / slope + 0.5;
float contracted_x = uv.x / depth;
final_uv = vec2(contracted_x,tilted_y);
}
else if (u_s3d_s == 2.0) {
float slope = 1.0 - tilt * (1.0 - uv.x);
float tilted_y = (uv.y - 0.5) / slope + 0.5;
float contracted_x = 1.0 - (1.0 - uv.x) / depth;
final_uv = vec2(contracted_x,tilted_y);
}
else if (u_s3d_s == 3.0) {
float slope = 1.0 - tilt * uv.y;
float tilted_x = (uv.x - 0.5) / slope + 0.5;
float contracted_y = uv.y / depth;
final_uv = vec2(tilted_x,contracted_y);
}
else if (u_s3d_s == 4.0) {
float slope = 1.0 - tilt * (1.0 - uv.y);
float tilted_x = (uv.x - 0.5) / slope + 0.5;
float contracted_y = 1.0 - (1.0 - uv.y) / depth;
final_uv = vec2(tilted_x,contracted_y);
}
if (final_uv.x < 0.0 || final_uv.x > 1.0 || final_uv.y < 0.0 || final_uv.y > 1.0) {
gl_FragColor = vec4(0.0);
} else {
gl_FragColor = texture2D(tex0,final_uv);
}
""")
transform MDX_s3d:
# 可选:
# 压缩图片时,临近像素颜色混合,会逐渐模糊
# 可以使用近邻取样(nearest-neighbor)过滤绘制来强化锐利边缘,但锯齿强烈的演出效果不如模糊...
nearest True
# 必须:
# 应对shader无法正确处理网格顶点的容器组件,例如Fixed(),或Solid()这种不是容器但同样处理不了顶点的
# 同时,打开后可以把子组件压成纹理,即整个组件整体应用,而不是每个子组件分别应用
mesh True
shader 'Maz.Side3D'
u_s3d_s 1 # side 轴向边,1234对应左右上下
u_s3d_t 0.0 # tilt 倾斜度
u_s3d_d 1.0 # depth 纵深度
linear 3.0 u_s3d_t 0.5 u_s3d_d 0.5
linear 3.0 u_s3d_t 0.0 u_s3d_d 1.0
repeat
#测试
screen abc():
fixed:
align(0.5,0.5)
xysize(500,400)
at MDX_s3d
frame:
xysize(500,400)
fixed:
align(0.55,0.55)
xysize(500,400)
at MDX_s3d
vbox:
text _("{size=68}画廊{/size}"):
outlines [ (1, "#f00", 0, 0 ) ]
textbutton "text" action NullAction()
额外内容:
我查阅了RotateMatrix()的源码
但也许由于我对矩阵以这类内容水平低下...效果十分奇怪
然后查阅了另一篇使用矩阵模仿3D的效果shader帖子,效果也很奇怪
都没能复现RotateMatrix(),在重复调试后无果,所以就放弃矩阵了
使用2D的思维,也就是实际上是两边分别倾斜,对边靠近,即宽度缩减的方式来模拟透视效果
虽然在数值上更加可控,但对3D来说是不严谨的...
但总归是搓出一个看起来是那么回事的东西(
#点击头像 查看我写的更多屎
粉身碎骨浑不怕,要留答辩在人间
|