Files
aya/client/common/shaders/bgfx_source/particle.sc
2025-12-17 16:47:48 +00:00

199 lines
5.5 KiB
Scala

$input a_position, a_texcoord0, a_texcoord1, a_texcoord2, a_texcoord3
$output v_texcoord0, v_texcoord1, v_color0
#include "common.sh"
SAMPLER2D(s_tex, 0);
SAMPLER2D(s_cstrip, 1);
SAMPLER2D(s_astrip, 2);
uniform vec4 u_throttleFactor; // .x = alpha cutoff, .y = alpha boost (clamp), .w - additive/alpha ratio for Crazy shaders
uniform vec4 u_modulateColor;
uniform vec4 u_zOffset;
vec4 rotScale(vec4 scaleRotLife)
{
float cr = cos(scaleRotLife.z);
float sr = sin(scaleRotLife.z);
vec4 r;
r.x = cr * scaleRotLife.x;
r.y = -sr * scaleRotLife.x;
r.z = sr * scaleRotLife.y;
r.w = cr * scaleRotLife.y;
return r;
}
vec4 mulq(vec4 a, vec4 b)
{
vec3 i = cross(a.xyz, b.xyz) + a.w * b.xyz + b.w * a.xyz;
float r = a.w * b.w - dot(a.xyz, b.xyz);
return vec4(i, r);
}
vec4 conj(vec4 a)
{
return vec4(-a.xyz, a.w);
}
vec4 rotate(vec4 v, vec4 q)
{
return mulq(mulq(q, v), conj(q));
}
vec4 axis_angle(vec3 axis, float angle)
{
return vec4(sin(angle/2.0) * axis, cos(angle/2.0));
}
void vs()
{
vec4 pos = vec4(a_position, 1.0);
vec2 disp = a_texcoord1.xy * 2.0 - 1.0; // -1..1
vec4 scaleRotLifeFlt = a_texcoord0 * vec4(1.0/256.0, 1.0/256.0, 2.0 * 3.1415926 / 32767.0, 1.0 / 32767.0);
scaleRotLifeFlt.xy += 127.0;
vec4 rs = rotScale(scaleRotLifeFlt);
pos += u_viewRight * dot(disp, rs.xy);
pos += u_viewUp * dot(disp, rs.zw);
vec4 pos2 = pos + u_viewDir * u_zOffset.x; // Z-offset position in world space
gl_Position = mul(u_viewProjection, pos);
v_texcoord0.xy = a_texcoord1.xy;
v_texcoord0.y = 1.0 - v_texcoord0.y;
v_texcoord0.z = (u_fogParams.z - gl_Position.w) * u_fogParams.w;
v_texcoord1.x = 1.0 - max(0.0, min(1.0, scaleRotLifeFlt.w));
v_texcoord1.y = a_texcoord2.x * (1.0 / 32767.0);
pos2 = mul(u_viewProjection, pos2); // Z-offset position in clip space
gl_Position.z = pos2.z * gl_Position.w / pos2.w; // Only need z
}
void psAdd()
{
vec4 texcolor = texture2D(s_tex, v_texcoord0.xy);
vec4 vcolor = texture2D(s_cstrip, v_texcoord1.xy);
vcolor.a = texture2D(s_astrip, v_texcoord1.xy).r;
vec4 result;
result.rgb = (texcolor.rgb + vcolor.rgb) * u_modulateColor.rgb;
result.a = texcolor.a * vcolor.a;
result.rgb *= result.a;
result.rgb = mix(vec3(0.0), result.rgb, saturate(v_texcoord0.zzz));
gl_FragColor = result;
}
void psModulate()
{
vec4 texcolor = texture2D(s_tex, v_texcoord0.xy);
vec4 vcolor = texture2D(s_cstrip, v_texcoord1.xy) * u_modulateColor;
vcolor.a = texture2D(s_astrip, v_texcoord1.xy).r * u_modulateColor.a;
vec4 result;
result.rgb = texcolor.rgb * vcolor.rgb;
result.a = texcolor.a * vcolor.a;
result.rgb = mix(u_fogColor.rgb, result.rgb, saturate(v_texcoord0.zzz));
gl_FragColor = result;
}
// - this shader is crazy
// - used instead of additive particles to help see bright particles (e.g. fire) on top of extremely bright backgrounds
// - requires ONE | INVSRCALPHA blend mode, useless otherwise
// - does not use color strip texture
// - outputs a blend between additive blend and alpha blend in fragment alpha
// - ratio multiplier is in throttleFactor.w
void psCrazy()
{
vec4 texcolor = texture2D(s_tex, v_texcoord0.xy);
vec4 vcolor = vec4(1.0, 0.0, 0.0, 0.0);
vcolor.a = texture2D(s_astrip, v_texcoord1.xy).r;
float blendRatio = u_throttleFactor.w;
vec4 result;
result.rgb = (texcolor.rgb) * u_modulateColor.rgb * vcolor.a * texcolor.a;
result.a = blendRatio * texcolor.a * vcolor.a;
result = mix(vec4(0.0), result, saturate(v_texcoord0.zzzz));
gl_FragColor = result;
}
void psCrazySparkles()
{
vec4 texcolor = texture2D(s_tex, v_texcoord0.xy);
vec4 vcolor = texture2D(s_cstrip, v_texcoord1.xy);
vcolor.a = texture2D(s_astrip, v_texcoord1.xy).r;
float blendRatio = u_throttleFactor.w;
vec4 result;
if (texcolor.a < 0.5)
{
result.rgb = vcolor.rgb * u_modulateColor.rgb * (2.0 * texcolor.a);
}
else
{
result.rgb = mix(vcolor.rgb * u_modulateColor.rgb, texcolor.rgb, 2.0 * texcolor.a - 1.0);
}
result.rgb *= vcolor.a;
result.a = blendRatio * texcolor.a * vcolor.a;
result = mix(vec4(0.0), result, saturate(v_texcoord0.zzzz));
gl_FragColor = result;
}
// Custom particle shader
void vsCustom()
{
vec4 pos = vec4(a_position, 1.0);
vec2 disp = a_texcoord1.xy * 2.0 - 1.0; // -1..1
vec4 scaleRotLifeFlt = a_texcoord0 * vec4(1.0/256.0, 1.0/256.0, 2.0 * 3.1415926 / 32767.0, 1.0 / 32767.0);
scaleRotLifeFlt.xy += 127.0;
vec4 rs = rotScale(scaleRotLifeFlt);
pos += u_viewRight * dot(disp, rs.xy);
pos += u_viewUp * dot(disp, rs.zw);
vec4 pos2 = pos + u_viewDir * u_zOffset.x; // Z-offset position in world space
gl_Position = mul(u_viewProjection, pos);
v_texcoord0.xy = a_texcoord1.xy;
v_texcoord0.y = 1.0 - v_texcoord0.y;
v_texcoord0.z = (u_fogParams.z - gl_Position.w) * u_fogParams.w;
v_color0 = a_texcoord3 * (1.0/255.0);
pos2 = mul(u_viewProjection, pos2); // Z-offset position in clip space
gl_Position.z = pos2.z * gl_Position.w / pos2.w; // Only need z
}
void psCustom()
{
vec4 texcolor = texture2D(s_tex, v_texcoord0.xy);
vec4 vcolor = v_color0;
float blendRatio = u_throttleFactor.w;
vec4 result;
result.rgb = texcolor.rgb * vcolor.rgb * vcolor.a * texcolor.a;
result.a = blendRatio * texcolor.a * vcolor.a;
result = mix(vec4(0.0), result, saturate(v_texcoord0.zzzz));
gl_FragColor = result;
}