OctaCore/config/glsl/volumetric.cfg

240 lines
10 KiB
INI

volopt = [ >= (strstr $volumetrictype $arg1) 0 ]
volumetricvariantshader = [
local volumetrictype
volumetrictype = $arg3
maxsteps = $arg4
spotlight = (>= $arg2 1)
variantshader 0 $arg1 $arg2 (? (< $arg2 0) [
in vec4 vvertex;
uniform mat4 lightmatrix;
void main(void)
{
gl_Position = lightmatrix * vvertex;
}
]) [
@(gfetchdefs tex3)
@(if (volopt "p") [
if (|| (volopt "g") (volopt "G")) [if (> $usetexgather 1) [result [
uniform sampler2DShadow tex4;
]] [result [
uniform sampler2D tex4;
]]] [result [
uniform sampler2DRectShadow tex4;
]]
])
uniform vec4 lightpos;
uniform vec3 lightcolor;
@(? $spotlight [
uniform vec4 spotparams;
])
@(? (volopt "p") [
uniform vec4 shadowparams;
uniform vec2 shadowoffset;
])
uniform vec3 camera;
uniform mat4 worldmatrix;
uniform vec4 fogdir;
uniform vec3 fogcolor;
uniform vec2 fogdensity;
uniform vec4 radialfogscale;
uniform vec2 shadowatlasscale;
uniform vec4 volscale;
uniform float volminstep;
uniform float voldistclamp;
uniform float volprefilter;
layout(location = 0) out vec4 fragcolor;
@(if (volopt "p") [
? $spotlight [
vec3 getspottc(vec3 dir, float spotdist)
{
vec2 mparams = shadowparams.xy / max(spotdist, 1e-5);
return vec3((dir.xy - spotparams.xy*(spotdist + (spotparams.z < 0.0 ? -1.0 : 1.0)*dir.z)*shadowparams.z) * mparams.x + shadowoffset, mparams.y + shadowparams.w);
}
] [
vec3 getshadowtc(vec3 dir)
{
vec3 adir = abs(dir);
float m = max(adir.x, adir.y), mz = max(adir.z, m);
vec2 mparams = shadowparams.xy / max(mz, 1e-5);
vec4 proj;
if(adir.x > adir.y) proj = vec4(dir.zyx, 0.0); else proj = vec4(dir.xzy, 1.0);
if(adir.z > m) proj = vec4(dir, 2.0);
return vec3(proj.xy * mparams.x + vec2(proj.w, step(proj.z, 0.0)) * shadowparams.z + shadowoffset, mparams.y + shadowparams.w);
}
]
])
@(if (volopt "p") [
if (|| (volopt "g") (volopt "G")) [
? (> $usetexgather 1) [
#define filtershadow(shadowtc) float(shadow(tex4, vec3(shadowtc.xy*shadowatlasscale, shadowtc.z)))
] [
#define filtershadow(shadowtc) step(shadowtc.z, float(texture(tex4, shadowtc.xy*shadowatlasscale)))
]
] [result [
#define filtershadow(shadowtc) float(textureRect(tex4, shadowtc))
]]
])
void main(void)
{
vec2 tc = gl_FragCoord.xy * volscale.xy;
@(gdepthunpack depth [gfetch(tex3, tc)] [
vec3 pos = (worldmatrix * vec4(depth*tc, depth, 1.0)).xyz;
] [
vec4 pos = worldmatrix * vec4(tc, depth, 1.0);
pos.xyz /= pos.w;
])
vec3 ray = pos.xyz - camera;
float dist2 = dot(ray, ray), invdist = inversesqrt(dist2), radialdist = min(dist2 * invdist, voldistclamp);
ray *= invdist;
vec3 camlight = lightpos.xyz - camera * lightpos.w;
float camlight2 = dot(camlight, camlight), v = dot(camlight, ray), d = v*v + 1.0 - camlight2;
float light = 0.0;
if(d > 0)
{
d = sqrt(d);
float front = v - d, back = v + d;
@(? $spotlight [
float spotangle = 1.0 - 1.0/spotparams.w, spotangle2 = spotangle*spotangle,
rayspot = dot(ray, spotparams.xyz), camspot = dot(camlight, spotparams.xyz),
qa = spotangle2 - rayspot*rayspot,
qb = rayspot*camspot - spotangle2*v,
qc = spotangle2*camlight2 - camspot*camspot,
disc = qb*qb - qa*qc;
if(disc > 0)
{
disc = abs(sqrt(disc)/qa);
float t = -qb/qa, t0 = t - disc, t1 = t + disc;
if(t0*rayspot < camspot) front = max(front, t1);
else if(t1*rayspot < camspot) back = min(back, t0);
else { front = max(front, t0); back = min(back, t1); }
])
float maxspace = back - front, stepdist = maxspace * @(divf 1.0 $maxsteps);
front = max(front, 0.0);
back = min(back, radialdist * lightpos.w);
float space = back - front;
if(space > volminstep*stepdist)
{
float dither = dot(fract((gl_FragCoord.xy - 0.5).xyxy*vec4(0.5, 0.5, 0.25, 0.25)), vec4(0.375, 0.9375, 0.25, 0.125));
vec3 lightdir = ray * (back + stepdist*dither) - camlight;
vec3 raystep = ray * -stepdist;
for(int i = 0; i < @maxsteps; i++)
{
lightdir += raystep;
@(if $spotlight [result [
float lightdist2 = dot(lightdir, lightdir);
float lightinvdist = inversesqrt(lightdist2);
float spotdist = dot(lightdir, spotparams.xyz);
float spotatten = 1.0 - (1.0 - lightinvdist * spotdist) * spotparams.w;
if(spotatten > 0.0)
{
float lightatten = clamp(1.0 - lightdist2 * lightinvdist, 0.0, 1.0) * spotatten;
@(? (volopt "p") [
vec3 spottc = getspottc(lightdir, spotdist);
lightatten *= filtershadow(spottc);
])
light += lightatten;
}
]] [result [
float lightatten = clamp(1.0 - length(lightdir), 0.0, 1.0);
@(? (volopt "p") [
vec3 shadowtc = getshadowtc(lightdir);
lightatten *= filtershadow(shadowtc);
])
light += lightatten;
]])
space -= stepdist;
if(space <= 0) break;
}
float fogcoord = front/lightpos.w;
float foglerp = clamp(exp2(fogcoord*fogdensity.x)*fogdensity.y, 0.0, 1.0);
light *= foglerp * stepdist;
@(? $spotlight [
light /= min(maxspace, 1.0);
])
}
@(? $spotlight [}])
}
vec2 weights = step(fwidth(radialdist), volprefilter) * (2.0*fract((gl_FragCoord.xy - 0.5)*0.5) - 0.5);
light -= dFdx(light) * weights.x;
light -= dFdy(light) * weights.y;
fragcolor.rgb = light * lightcolor;
fragcolor.a = 0.0;
}
]
]
volumetricshader = [
volumetrictype = (concatword $arg1 $arg2)
shadername = (concatword "volumetric" $volumetrictype $arg3)
volumetricvariantshader $shadername -1 $arg1 $arg3
volumetricvariantshader $shadername 0 (concatword $arg1 $arg2) $arg3
if (volopt "s") [
volumetricvariantshader $shadername 1 $arg1 $arg3
volumetricvariantshader $shadername 2 (concatword $arg1 $arg2) $arg3
]
]
volumetricbilateralvariantshader = [
numtaps = $arg2
reduced = $arg3
filterdir = $arg4
shader 0 $arg1 [
in vec4 vvertex;
@(if $reduced [result [
@(screentexcoord 0)
out vec2 texcoord0;
]])
void main(void)
{
gl_Position = vvertex;
@(? $reduced [texcoord0 = vtexcoord0;])
}
] [
@(gfetchdefs tex3)
uniform sampler2DRect tex0;
uniform vec2 bilateralparams;
@(? $reduced [in vec2 texcoord0;])
layout(location = 0) out vec4 fragcolor;
void main(void)
{
#define tc gl_FragCoord.xy
#define depthtc @(? $reduced [texcoord0] [gl_FragCoord.xy])
#define tapvec(type, i) @(? (=s $filterdir "x") [type(i, 0.0)] [type(0.0, i)])
#define texval(i) textureRect(tex0, tc + tapvec(vec2, i))
#define texvaloffset(i) textureRectOffset(tex0, tc, tapvec(ivec2, i))
#define depthval(i) gfetch(tex3, depthtc + tapvec(vec2, i))
#define depthvaloffset(i) gfetchoffset(tex3, depthtc, tapvec(ivec2, i))
vec3 color = textureRect(tex0, tc).rgb;
@(gdepthunpack depth [gfetch(tex3, depthtc)])
float weights = 1.0;
@(loopconcat i (* 2 $numtaps) [
curtap = (- $i $numtaps)
if (>= $curtap 0) [curtap = (+ $curtap 1)]
curtapoffset = (* $curtap 2)
curdepthoffset = (<< $curtapoffset $reduced)
curtexval = [texval@(? (<= $mintexrectoffset $curtapoffset $maxtexrectoffset) "offset")(@(+f $curtapoffset))]
curdepthval = [depthval@(? (<= $mintexrectoffset $curdepthoffset $maxtexrectoffset) "offset")(@(+f $curdepthoffset))]
result [
vec3 color@[i] = @[curtexval].rgb;
@(gdepthunpack [depth@[i]] $curdepthval)
depth@[i] -= depth;
float weight@[i] = exp2(@(-f 0 (* $curtap $curtap))*bilateralparams.x - depth@[i]*depth@[i]*bilateralparams.y);
weights += weight@[i];
color += weight@[i] * color@[i];
]
])
fragcolor = vec4(color / weights, 0.0);
}
]
]
volumetricbilateralshader = [
volumetricbilateralvariantshader (concatword "volumetricbilateralx" $arg1 $arg2) $arg1 $arg2 x
volumetricbilateralvariantshader (concatword "volumetricbilateraly" $arg1 $arg2) $arg1 $arg2 y
]