forked from OctaForge/OctaCore
375 lines
11 KiB
INI
375 lines
11 KiB
INI
|
////////////////////////////////////////////////
|
||
|
//
|
||
|
// model shaders
|
||
|
//
|
||
|
////////////////////////////////////////////////
|
||
|
|
||
|
// skeletal animation with dual quaternions
|
||
|
|
||
|
qtangentdecode = [
|
||
|
? $arg1 [
|
||
|
vec4 qxyz = mquat.xxyy*mquat.yzyz, qxzw = vec4(mquat.xzw, -mquat.w);
|
||
|
vec3 mtangent = (qxzw.yzw*mquat.zzy + qxyz.zxy)*vec3(-2.0, 2.0, 2.0) + vec3(1.0, 0.0, 0.0);
|
||
|
vec3 mnormal = (qxzw.zwx*mquat.yxx + qxyz.ywz)*vec3(2.0, 2.0, -2.0) + vec3(0.0, 0.0, 1.0);
|
||
|
// vec3 mtangent = cross(mquat.xyz, vec3(mquat.wz, -mquat.y))*2.0 + vec3(1.0, 0.0, 0.0);
|
||
|
// vec3 mnormal = cross(mquat.xyz, vec3(mquat.y, -mquat.x, mquat.w))*2.0 + vec3(0.0, 0.0, 1.0);
|
||
|
] [
|
||
|
vec3 mnormal = cross(mquat.xyz, vec3(mquat.y, -mquat.x, mquat.w))*2.0 + vec3(0.0, 0.0, 1.0);
|
||
|
]
|
||
|
]
|
||
|
|
||
|
skelanimdefs = [
|
||
|
result [
|
||
|
attribute vec4 vboneweight, vboneindex;
|
||
|
//:uniform animdata
|
||
|
uniform vec4 animdata[@@(min $maxvsuniforms $maxskelanimdata)];
|
||
|
]
|
||
|
]
|
||
|
|
||
|
skelanim = [
|
||
|
result [
|
||
|
int index = int(vboneindex.x);
|
||
|
@(if (= $arg1 1) [result [
|
||
|
vec4 dqreal = animdata[index];
|
||
|
vec4 dqdual = animdata[index+1];
|
||
|
]] [result [
|
||
|
vec4 dqreal = animdata[index] * vboneweight.x;
|
||
|
vec4 dqdual = animdata[index+1] * vboneweight.x;
|
||
|
index = int(vboneindex.y);
|
||
|
dqreal += animdata[index] * vboneweight.y;
|
||
|
dqdual += animdata[index+1] * vboneweight.y;
|
||
|
@(if (>= $arg1 3) [result [
|
||
|
index = int(vboneindex.z);
|
||
|
dqreal += animdata[index] * vboneweight.z;
|
||
|
dqdual += animdata[index+1] * vboneweight.z;
|
||
|
]])
|
||
|
@(if (>= $arg1 4) [result [
|
||
|
index = int(vboneindex.w);
|
||
|
dqreal += animdata[index] * vboneweight.w;
|
||
|
dqdual += animdata[index+1] * vboneweight.w;
|
||
|
]])
|
||
|
float len = length(dqreal);
|
||
|
dqreal /= len;
|
||
|
dqdual /= len;
|
||
|
]])
|
||
|
|
||
|
vec4 mpos = vec4((cross(dqreal.xyz, cross(dqreal.xyz, vvertex.xyz) + vvertex.xyz*dqreal.w + dqdual.xyz) + dqdual.xyz*dqreal.w - dqreal.xyz*dqdual.w)*2.0 + vvertex.xyz, vvertex.w);
|
||
|
|
||
|
@(if (>= $numargs 2) [result [
|
||
|
vec4 mquat = vec4(cross(dqreal.xyz, vtangent.xyz) + dqreal.xyz*vtangent.w + vtangent.xyz*dqreal.w, dqreal.w*vtangent.w - dot(dqreal.xyz, vtangent.xyz));
|
||
|
@(qtangentdecode $arg2)
|
||
|
]])
|
||
|
]
|
||
|
]
|
||
|
|
||
|
// mdltype:
|
||
|
// a -> alpha test
|
||
|
// b -> dual-quat skeletal animation
|
||
|
|
||
|
mdlopt = [ >= (strstr $modeltype $arg1) 0 ]
|
||
|
|
||
|
shadowmodelvertexshader = [
|
||
|
local modeltype
|
||
|
modeltype = $arg1
|
||
|
result [
|
||
|
attribute vec4 vvertex;
|
||
|
@(if (mdlopt "b") [skelanimdefs $arg2])
|
||
|
uniform mat4 modelmatrix;
|
||
|
@(? (mdlopt "a") [
|
||
|
attribute vec2 vtexcoord0;
|
||
|
uniform vec2 texscroll;
|
||
|
varying vec2 texcoord0;
|
||
|
])
|
||
|
void main(void)
|
||
|
{
|
||
|
@(if (mdlopt "b") [
|
||
|
skelanim $arg2
|
||
|
] [result [
|
||
|
#define mpos vvertex
|
||
|
]])
|
||
|
|
||
|
gl_Position = modelmatrix * mpos;
|
||
|
|
||
|
@(? (mdlopt "a") [
|
||
|
texcoord0 = vtexcoord0 + texscroll;
|
||
|
])
|
||
|
}
|
||
|
]
|
||
|
]
|
||
|
|
||
|
shadowmodelfragmentshader = [
|
||
|
local modeltype
|
||
|
modeltype = $arg1
|
||
|
result [
|
||
|
@(? (mdlopt "a") [
|
||
|
uniform sampler2D tex0;
|
||
|
uniform float alphatest;
|
||
|
varying vec2 texcoord0;
|
||
|
])
|
||
|
void main(void)
|
||
|
{
|
||
|
@(? (mdlopt "a") [
|
||
|
vec4 color = texture2D(tex0, texcoord0);
|
||
|
if(color.a <= alphatest)
|
||
|
discard;
|
||
|
])
|
||
|
}
|
||
|
]
|
||
|
]
|
||
|
|
||
|
shadowmodelshader = [
|
||
|
defershader 0 $arg1 [
|
||
|
shader 0 @arg1 (shadowmodelvertexshader @arg2) (shadowmodelfragmentshader @arg2)
|
||
|
loop+ i 1 4 [
|
||
|
variantshader 0 @@arg1 0 (shadowmodelvertexshader @@(concatword $arg2 "b") $i) []
|
||
|
]
|
||
|
]
|
||
|
]
|
||
|
|
||
|
shadowmodelshader "shadowmodel" ""
|
||
|
shadowmodelshader "alphashadowmodel" "a"
|
||
|
|
||
|
// mdltype:
|
||
|
// a -> alpha test
|
||
|
// e -> envmap
|
||
|
// n -> normalmap
|
||
|
// m -> masks
|
||
|
// d -> decal
|
||
|
// D -> alpha decal
|
||
|
// b -> dual-quat skeletal animation
|
||
|
// c -> disable cullface
|
||
|
// t -> transparent
|
||
|
|
||
|
modelvertexshader = [
|
||
|
local modeltype
|
||
|
modeltype = $arg1
|
||
|
result [
|
||
|
attribute vec4 vvertex, vtangent;
|
||
|
attribute vec2 vtexcoord0;
|
||
|
@(if (mdlopt "b") [skelanimdefs $arg2 (mdlopt "n")])
|
||
|
uniform mat4 modelmatrix;
|
||
|
uniform mat3 modelworld;
|
||
|
uniform vec3 modelcamera;
|
||
|
uniform vec2 texscroll;
|
||
|
@(? (mdlopt "n") [
|
||
|
varying mat3 world;
|
||
|
] [
|
||
|
varying vec3 nvec;
|
||
|
])
|
||
|
@(? (mdlopt "e") [
|
||
|
varying vec3 camvec;
|
||
|
])
|
||
|
@(msaainterpvert)
|
||
|
varying vec2 texcoord0;
|
||
|
|
||
|
void main(void)
|
||
|
{
|
||
|
@(if (mdlopt "b") [
|
||
|
skelanim $arg2 (mdlopt "n")
|
||
|
] [result [
|
||
|
#define mpos vvertex
|
||
|
#define mquat vtangent
|
||
|
@(qtangentdecode (mdlopt "n"))
|
||
|
]])
|
||
|
|
||
|
gl_Position = modelmatrix * mpos;
|
||
|
|
||
|
texcoord0 = vtexcoord0 + texscroll;
|
||
|
|
||
|
@(msaapackvert)
|
||
|
|
||
|
@(? (mdlopt "e") [
|
||
|
camvec = modelworld * normalize(modelcamera - mpos.xyz);
|
||
|
])
|
||
|
|
||
|
@(? (mdlopt "n") [
|
||
|
// composition of tangent -> object and object -> world transforms
|
||
|
// becomes tangent -> world
|
||
|
vec3 wnormal = modelworld * mnormal;
|
||
|
vec3 wtangent = modelworld * mtangent;
|
||
|
vec3 wbitangent = cross(wnormal, wtangent) * (vtangent.w < 0.0 ? -1.0 : 1.0);
|
||
|
world = mat3(wtangent, wbitangent, wnormal);
|
||
|
] [
|
||
|
nvec = modelworld * mnormal;
|
||
|
])
|
||
|
}
|
||
|
]
|
||
|
]
|
||
|
|
||
|
modelfragmentshader = [
|
||
|
local modeltype
|
||
|
modeltype = $arg1
|
||
|
result [
|
||
|
@(? (mdlopt "n") [
|
||
|
varying mat3 world;
|
||
|
] [
|
||
|
varying vec3 nvec;
|
||
|
])
|
||
|
@(? (mdlopt "e") [
|
||
|
uniform vec2 envmapscale;
|
||
|
varying vec3 camvec;
|
||
|
])
|
||
|
uniform vec4 colorscale;
|
||
|
uniform vec2 fullbright;
|
||
|
uniform vec3 maskscale;
|
||
|
@(? (mdlopt "a") [uniform float alphatest;])
|
||
|
uniform sampler2D tex0;
|
||
|
@(? (mdlopt "m") [uniform sampler2D tex1;])
|
||
|
@(? (mdlopt "e") [uniform samplerCube tex2;])
|
||
|
@(? (mdlopt "n") [uniform sampler2D tex3;])
|
||
|
@(? (|| (mdlopt "d") [mdlopt "D"]) [uniform sampler2D tex4;])
|
||
|
@(msaainterpfrag)
|
||
|
varying vec2 texcoord0;
|
||
|
uniform float aamask;
|
||
|
|
||
|
void main(void)
|
||
|
{
|
||
|
vec4 diffuse = texture2D(tex0, texcoord0);
|
||
|
|
||
|
@(? (mdlopt "a") [
|
||
|
if(diffuse.a <= alphatest)
|
||
|
discard;
|
||
|
])
|
||
|
|
||
|
gcolor.rgb = diffuse.rgb*colorscale.rgb;
|
||
|
|
||
|
@(? (|| (mdlopt "d") [mdlopt "D"]) [
|
||
|
vec4 decal = texture2D(tex4, texcoord0);
|
||
|
@(? (mdlopt "D") [
|
||
|
gcolor.rgb = mix(gcolor.rgb, decal.rgb, decal.a);
|
||
|
] [
|
||
|
gcolor.rgb += decal.rgb;
|
||
|
])
|
||
|
])
|
||
|
|
||
|
@(if (mdlopt "n") [result [
|
||
|
vec3 normal = texture2D(tex3, texcoord0).rgb - 0.5;
|
||
|
@(? (mdlopt "c") [
|
||
|
if(!gl_FrontFacing) normal.z = -normal.z;
|
||
|
])
|
||
|
normal = normalize(world * normal);
|
||
|
]] [result [
|
||
|
vec3 normal = normalize(nvec);
|
||
|
@(? (mdlopt "c") [
|
||
|
if(!gl_FrontFacing) normal = -normal;
|
||
|
])
|
||
|
]])
|
||
|
|
||
|
float spec = maskscale.x;
|
||
|
@(if (mdlopt "m") [result [
|
||
|
vec3 masks = texture2D(tex1, texcoord0).rgb;
|
||
|
spec *= masks.r; // specmap in red channel
|
||
|
|
||
|
@(? (mdlopt "e") [
|
||
|
vec3 camn = normalize(camvec);
|
||
|
float invfresnel = dot(camn, normal);
|
||
|
vec3 rvec = 2.0*invfresnel*normal - camn;
|
||
|
float rmod = envmapscale.x*clamp(invfresnel, 0.0, 1.0) + envmapscale.y;
|
||
|
vec3 reflect = textureCube(tex2, rvec).rgb;
|
||
|
gcolor.rgb = mix(gcolor.rgb, reflect, rmod*masks.b); // envmap mask in blue channel
|
||
|
])
|
||
|
|
||
|
float glowk = max(maskscale.z*masks.g, fullbright.y); // glow mask in green channel
|
||
|
]] [result [
|
||
|
float glowk = fullbright.y;
|
||
|
]])
|
||
|
@(gspecpack maskscale.y spec)
|
||
|
|
||
|
float colork = clamp(fullbright.x - glowk, 0.0, 1.0);
|
||
|
|
||
|
@(if (mdlopt "t") [result [
|
||
|
gcolor *= colorscale.a;
|
||
|
gglow.rgb = gcolor.rgb*glowk;
|
||
|
gcolor.rgb *= colork;
|
||
|
#define packnorm colorscale.a
|
||
|
]] [gglowpack "" packnorm])
|
||
|
|
||
|
@(gnormpackdef normal packnorm)
|
||
|
|
||
|
@(msaapackfrag aamask)
|
||
|
}
|
||
|
]
|
||
|
]
|
||
|
|
||
|
modelshader = [
|
||
|
shadername = (concatword "model" $arg1)
|
||
|
maxvariants = 9
|
||
|
shader 0 $shadername (modelvertexshader $arg1) (modelfragmentshader $arg1)
|
||
|
loop+ i 1 4 [
|
||
|
variantshader 0 $shadername 0 (modelvertexshader (concatword $arg1 "b") $i) [] $maxvariants
|
||
|
]
|
||
|
variantshader 0 $shadername 1 [] (modelfragmentshader (concatword $arg1 "t")) $maxvariants
|
||
|
loop i 4 [
|
||
|
variantshader 0 $shadername 1 [0 , @i] 1 $maxvariants
|
||
|
]
|
||
|
]
|
||
|
|
||
|
rsmmodelvertexshader = [
|
||
|
local modeltype
|
||
|
modeltype = $arg1
|
||
|
result [
|
||
|
attribute vec4 vvertex, vtangent;
|
||
|
attribute vec2 vtexcoord0;
|
||
|
@(if (mdlopt "b") [skelanimdefs $arg2 (mdlopt "n")])
|
||
|
uniform mat4 modelmatrix;
|
||
|
uniform mat3 modelworld;
|
||
|
uniform vec2 texscroll;
|
||
|
varying vec2 texcoord0;
|
||
|
varying vec3 nvec;
|
||
|
void main(void)
|
||
|
{
|
||
|
@(if (mdlopt "b") [
|
||
|
skelanim $arg2 (mdlopt "n")
|
||
|
] [result [
|
||
|
#define mpos vvertex
|
||
|
#define mquat vtangent
|
||
|
@(qtangentdecode (mdlopt "n"))
|
||
|
]])
|
||
|
|
||
|
gl_Position = modelmatrix * mpos;
|
||
|
|
||
|
texcoord0 = vtexcoord0 + texscroll;
|
||
|
|
||
|
nvec = modelworld * mnormal;
|
||
|
}
|
||
|
]
|
||
|
]
|
||
|
|
||
|
rsmmodelfragmentshader = [
|
||
|
local modeltype
|
||
|
modeltype = $arg1
|
||
|
result [
|
||
|
varying vec2 texcoord0;
|
||
|
varying vec3 nvec;
|
||
|
uniform vec4 colorscale;
|
||
|
@(? (mdlopt "a") [uniform float alphatest;])
|
||
|
uniform vec3 rsmdir;
|
||
|
uniform sampler2D tex0;
|
||
|
fragdata(0) vec4 gcolor;
|
||
|
fragdata(1) vec4 gnormal;
|
||
|
void main(void)
|
||
|
{
|
||
|
vec4 diffuse = texture2D(tex0, texcoord0);
|
||
|
@(? (mdlopt "a") [
|
||
|
if(diffuse.a <= alphatest)
|
||
|
discard;
|
||
|
])
|
||
|
vec3 normal = normalize(nvec);
|
||
|
@(? (mdlopt "c") [
|
||
|
if(!gl_FrontFacing) normal = -normal;
|
||
|
])
|
||
|
gcolor = vec4(dot(normal, rsmdir)*diffuse.rgb*colorscale.rgb, 1.0);
|
||
|
gnormal = vec4(normal*0.5+0.5, 0.0);
|
||
|
}
|
||
|
]
|
||
|
]
|
||
|
|
||
|
rsmmodelshader = [
|
||
|
shadername = (concatword "rsmmodel" $arg1)
|
||
|
shader 0 $shadername (rsmmodelvertexshader $arg1) (rsmmodelfragmentshader $arg1)
|
||
|
loop+ i 1 4 [
|
||
|
variantshader 0 $shadername 0 (rsmmodelvertexshader (concatword $arg1 "b") $i) []
|
||
|
]
|
||
|
]
|
||
|
|