forked from OctaForge/OctaCore
240 lines
10 KiB
INI
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) [
|
||
|
attribute 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;
|
||
|
fragdata(0) 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(shadow2D(tex4, vec3(shadowtc.xy*shadowatlasscale, shadowtc.z)))
|
||
|
] [
|
||
|
#define filtershadow(shadowtc) step(shadowtc.z, float(texture2D(tex4, shadowtc.xy*shadowatlasscale)))
|
||
|
]
|
||
|
] [result [
|
||
|
#define filtershadow(shadowtc) float(shadow2DRect(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 [
|
||
|
attribute vec4 vvertex;
|
||
|
@(if $reduced [result [
|
||
|
@(screentexcoord 0)
|
||
|
varying vec2 texcoord0;
|
||
|
]])
|
||
|
void main(void)
|
||
|
{
|
||
|
gl_Position = vvertex;
|
||
|
@(? $reduced [texcoord0 = vtexcoord0;])
|
||
|
}
|
||
|
] [
|
||
|
@(gfetchdefs tex3)
|
||
|
uniform sampler2DRect tex0;
|
||
|
uniform vec2 bilateralparams;
|
||
|
@(? $reduced [varying vec2 texcoord0;])
|
||
|
fragdata(0) 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) texture2DRect(tex0, tc + tapvec(vec2, i))
|
||
|
#define texvaloffset(i) texture2DRectOffset(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 = texture2DRect(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
|
||
|
]
|
||
|
|