//////////////////////////////////////////////// // // 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 [ in 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 [ in vec4 vvertex; @(if (mdlopt "b") [skelanimdefs $arg2]) uniform mat4 modelmatrix; @(? (mdlopt "a") [ in vec2 vtexcoord0; uniform vec2 texscroll; out 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; in vec2 texcoord0; ]) void main(void) { @(? (mdlopt "a") [ vec4 color = texture(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 [ in vec4 vvertex, vtangent; in vec2 vtexcoord0; @(if (mdlopt "b") [skelanimdefs $arg2 (mdlopt "n")]) uniform mat4 modelmatrix; uniform mat3 modelworld; uniform vec3 modelcamera; uniform vec2 texscroll; @(? (mdlopt "n") [ out mat3 world; ] [ out vec3 nvec; ]) @(? (mdlopt "e") [ out vec3 camvec; ]) @(msaainterpvert) out 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") [ in mat3 world; ] [ in vec3 nvec; ]) @(? (mdlopt "e") [ uniform vec2 envmapscale; in 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) in vec2 texcoord0; uniform float aamask; void main(void) { vec4 diffuse = texture(tex0, texcoord0); @(? (mdlopt "a") [ if(diffuse.a <= alphatest) discard; ]) gcolor.rgb = diffuse.rgb*colorscale.rgb; @(? (|| (mdlopt "d") [mdlopt "D"]) [ vec4 decal = texture(tex4, texcoord0); @(? (mdlopt "D") [ gcolor.rgb = mix(gcolor.rgb, decal.rgb, decal.a); ] [ gcolor.rgb += decal.rgb; ]) ]) @(if (mdlopt "n") [result [ vec3 normal = texture(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 = texture(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 = texture(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 [ in vec4 vvertex, vtangent; in vec2 vtexcoord0; @(if (mdlopt "b") [skelanimdefs $arg2 (mdlopt "n")]) uniform mat4 modelmatrix; uniform mat3 modelworld; uniform vec2 texscroll; out vec2 texcoord0; out 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 [ in vec2 texcoord0; in vec3 nvec; uniform vec4 colorscale; @(? (mdlopt "a") [uniform float alphatest;]) uniform vec3 rsmdir; uniform sampler2D tex0; layout(location = 0) out vec4 gcolor; layout(location = 1) out vec4 gnormal; void main(void) { vec4 diffuse = texture(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) [] ] ]