1//////////////////////////////////////////////// 2// 3// model shaders 4// 5//////////////////////////////////////////////// 6 7// skeletal animation with dual quaternions 8 9qtangentdecode = [ 10 ? $arg1 [ 11 vec4 qxyz = mquat.xxyy*mquat.yzyz, qxzw = vec4(mquat.xzw, -mquat.w); 12 vec3 mtangent = (qxzw.yzw*mquat.zzy + qxyz.zxy)*vec3(-2.0, 2.0, 2.0) + vec3(1.0, 0.0, 0.0); 13 vec3 mnormal = (qxzw.zwx*mquat.yxx + qxyz.ywz)*vec3(2.0, 2.0, -2.0) + vec3(0.0, 0.0, 1.0); 14 // vec3 mtangent = cross(mquat.xyz, vec3(mquat.wz, -mquat.y))*2.0 + vec3(1.0, 0.0, 0.0); 15 // vec3 mnormal = cross(mquat.xyz, vec3(mquat.y, -mquat.x, mquat.w))*2.0 + vec3(0.0, 0.0, 1.0); 16 ] [ 17 vec3 mnormal = cross(mquat.xyz, vec3(mquat.y, -mquat.x, mquat.w))*2.0 + vec3(0.0, 0.0, 1.0); 18 ] 19] 20 21skelanimdefs = [ 22 result [ 23 attribute vec4 vboneweight, vboneindex; 24 #pragma CUBE2_uniform animdata 25 uniform vec4 animdata[@@(min $maxvsuniforms $maxskelanimdata)]; 26 ] 27] 28 29skelanim = [ 30 result [ 31 int index = int(vboneindex.x); 32 @(if (= $arg1 1) [result [ 33 vec4 dqreal = animdata[index]; 34 vec4 dqdual = animdata[index+1]; 35 ]] [result [ 36 vec4 dqreal = animdata[index] * vboneweight.x; 37 vec4 dqdual = animdata[index+1] * vboneweight.x; 38 index = int(vboneindex.y); 39 dqreal += animdata[index] * vboneweight.y; 40 dqdual += animdata[index+1] * vboneweight.y; 41 @(if (>= $arg1 3) [result [ 42 index = int(vboneindex.z); 43 dqreal += animdata[index] * vboneweight.z; 44 dqdual += animdata[index+1] * vboneweight.z; 45 ]]) 46 @(if (>= $arg1 4) [result [ 47 index = int(vboneindex.w); 48 dqreal += animdata[index] * vboneweight.w; 49 dqdual += animdata[index+1] * vboneweight.w; 50 ]]) 51 float len = length(dqreal); 52 dqreal /= len; 53 dqdual /= len; 54 ]]) 55 56 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); 57 58 @(if (>= $numargs 2) [result [ 59 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)); 60 @(qtangentdecode $arg2) 61 ]]) 62 ] 63] 64 65// mdltype: 66// a -> alpha test 67// b -> dual-quat skeletal animation 68 69mdlopt = [ >= (strstr $modeltype $arg1) 0 ] 70 71shadowmodelvertexshader = [ 72 local modeltype 73 modeltype = $arg1 74 result [ 75 attribute vec4 vvertex; 76 @(if (mdlopt "b") [skelanimdefs $arg2]) 77 uniform mat4 modelmatrix; 78 @(? (mdlopt "a") [ 79 attribute vec2 vtexcoord0; 80 uniform vec2 texscroll; 81 varying vec2 texcoord0; 82 ]) 83 void main(void) 84 { 85 @(if (mdlopt "b") [ 86 skelanim $arg2 87 ] [result [ 88 #define mpos vvertex 89 ]]) 90 91 gl_Position = modelmatrix * mpos; 92 93 @(? (mdlopt "a") [ 94 texcoord0 = vtexcoord0 + texscroll; 95 ]) 96 } 97 ] 98] 99 100shadowmodelfragmentshader = [ 101 local modeltype 102 modeltype = $arg1 103 result [ 104 @(? (mdlopt "a") [ 105 uniform sampler2D tex0; 106 uniform float alphatest; 107 varying vec2 texcoord0; 108 ]) 109 void main(void) 110 { 111 @(? (mdlopt "a") [ 112 vec4 color = texture2D(tex0, texcoord0); 113 if(color.a <= alphatest) 114 discard; 115 ]) 116 } 117 ] 118] 119 120shadowmodelshader = [ 121 defershader 0 $arg1 [ 122 shader 0 @arg1 (shadowmodelvertexshader @arg2) (shadowmodelfragmentshader @arg2) 123 loop+ i 1 4 [ 124 variantshader 0 @@arg1 0 (shadowmodelvertexshader @@(concatword $arg2 "b") $i) [] 125 ] 126 ] 127] 128 129shadowmodelshader "shadowmodel" "" 130shadowmodelshader "alphashadowmodel" "a" 131 132// mdltype: 133// a -> alpha test 134// e -> envmap 135// n -> normalmap 136// m -> masks 137// d -> decal 138// D -> alpha decal 139// b -> dual-quat skeletal animation 140// c -> disable cullface 141// t -> transparent 142 143modelvertexshader = [ 144 local modeltype 145 modeltype = $arg1 146 result [ 147 attribute vec4 vvertex, vtangent; 148 attribute vec2 vtexcoord0; 149 @(if (mdlopt "b") [skelanimdefs $arg2 (mdlopt "n")]) 150 uniform mat4 modelmatrix; 151 uniform mat3 modelworld; 152 uniform vec3 modelcamera; 153 uniform vec2 texscroll; 154 @(? (mdlopt "n") [ 155 varying mat3 world; 156 ] [ 157 varying vec3 nvec; 158 ]) 159 @(? (mdlopt "e") [ 160 varying vec3 camvec; 161 ]) 162 @(msaainterpvert) 163 varying vec2 texcoord0; 164 165 void main(void) 166 { 167 @(if (mdlopt "b") [ 168 skelanim $arg2 (mdlopt "n") 169 ] [result [ 170 #define mpos vvertex 171 #define mquat vtangent 172 @(qtangentdecode (mdlopt "n")) 173 ]]) 174 175 gl_Position = modelmatrix * mpos; 176 177 texcoord0 = vtexcoord0 + texscroll; 178 179 @(msaapackvert) 180 181 @(? (mdlopt "e") [ 182 camvec = modelworld * normalize(modelcamera - mpos.xyz); 183 ]) 184 185 @(? (mdlopt "n") [ 186 // composition of tangent -> object and object -> world transforms 187 // becomes tangent -> world 188 vec3 wnormal = modelworld * mnormal; 189 vec3 wtangent = modelworld * mtangent; 190 vec3 wbitangent = cross(wnormal, wtangent) * (vtangent.w < 0.0 ? -1.0 : 1.0); 191 world = mat3(wtangent, wbitangent, wnormal); 192 ] [ 193 nvec = modelworld * mnormal; 194 ]) 195 } 196 ] 197] 198 199modelfragmentshader = [ 200 local modeltype 201 modeltype = $arg1 202 result [ 203 @(? (mdlopt "n") [ 204 varying mat3 world; 205 ] [ 206 varying vec3 nvec; 207 ]) 208 @(? (mdlopt "e") [ 209 uniform vec2 envmapscale; 210 varying vec3 camvec; 211 ]) 212 uniform vec4 colorscale; 213 uniform vec2 fullbright; 214 uniform vec2 maskscale; 215 @(? (mdlopt "a") [uniform float alphatest;]) 216 uniform sampler2D tex0; 217 @(? (mdlopt "m") [uniform sampler2D tex1;]) 218 @(? (mdlopt "e") [uniform samplerCube tex2;]) 219 @(? (mdlopt "n") [uniform sampler2D tex3;]) 220 @(? (|| (mdlopt "d") [mdlopt "D"]) [uniform sampler2D tex4;]) 221 @(msaainterpfrag) 222 varying vec2 texcoord0; 223 uniform float aamask; 224 225 void main(void) 226 { 227 vec4 diffuse = texture2D(tex0, texcoord0); 228 229 @(? (mdlopt "a") [ 230 if(diffuse.a <= alphatest) 231 discard; 232 ]) 233 234 gcolor.rgb = diffuse.rgb*colorscale.rgb; 235 236 @(? (|| (mdlopt "d") [mdlopt "D"]) [ 237 vec4 decal = texture2D(tex4, texcoord0); 238 @(? (mdlopt "D") [ 239 gcolor.rgb = mix(gcolor.rgb, decal.rgb, decal.a); 240 ] [ 241 gcolor.rgb += decal.rgb; 242 ]) 243 ]) 244 245 @(if (mdlopt "n") [result [ 246 vec3 normal = texture2D(tex3, texcoord0).rgb - 0.5; 247 @(? (mdlopt "c") [ 248 if(!gl_FrontFacing) normal.z = -normal.z; 249 ]) 250 normal = normalize(world * normal); 251 ]] [result [ 252 vec3 normal = normalize(nvec); 253 @(? (mdlopt "c") [ 254 if(!gl_FrontFacing) normal = -normal; 255 ]) 256 ]]) 257 258 float spec = maskscale.x; 259 @(if (mdlopt "m") [result [ 260 vec3 masks = texture2D(tex1, texcoord0).rgb; 261 spec *= masks.r; // specmap in red channel 262 263 @(? (mdlopt "e") [ 264 vec3 camn = normalize(camvec); 265 float invfresnel = dot(camn, normal); 266 vec3 rvec = 2.0*invfresnel*normal - camn; 267 float rmod = envmapscale.x*clamp(invfresnel, 0.0, 1.0) + envmapscale.y; 268 vec3 reflect = textureCube(tex2, rvec).rgb; 269 gcolor.rgb = mix(gcolor.rgb, reflect, rmod*masks.b); // envmap mask in blue channel 270 ]) 271 ]]) 272 gcolor.a = 0.5*spec; 273 274 @(? (mdlopt "m") [ 275 float glowk = max(maskscale.y*masks.g, fullbright.y), colork = max(fullbright.x-glowk, 0.0); // glow mask in green channel 276 ] [ 277 float glowk = fullbright.y, colork = fullbright.x-fullbright.y; 278 ]) 279 280 @(if (mdlopt "t") [result [ 281 gglow.rgb = gcolor.rgb*glowk; 282 gcolor.rgb *= colork; 283 #define packnorm colorscale.a 284 ]] [gglowpack "" packnorm]) 285 286 @(gnormpackdef normal packnorm) 287 288 @(msaapackfrag aamask) 289 } 290 ] 291] 292 293modelshader = [ 294 shadername = (concatword "model" $arg1) 295 maxvariants = 9 296 shader 0 $shadername (modelvertexshader $arg1) (modelfragmentshader $arg1) 297 loop+ i 1 4 [ 298 variantshader 0 $shadername 0 (modelvertexshader (concatword $arg1 "b") $i) [] $maxvariants 299 ] 300 variantshader 0 $shadername 1 [] (modelfragmentshader (concatword $arg1 "t")) $maxvariants 301 loop i 4 [ 302 variantshader 0 $shadername 1 [0 , @i] 1 $maxvariants 303 ] 304] 305 306rsmmodelvertexshader = [ 307 local modeltype 308 modeltype = $arg1 309 result [ 310 attribute vec4 vvertex, vtangent; 311 attribute vec2 vtexcoord0; 312 @(if (mdlopt "b") [skelanimdefs $arg2 (mdlopt "n")]) 313 uniform mat4 modelmatrix; 314 uniform mat3 modelworld; 315 uniform vec2 texscroll; 316 varying vec2 texcoord0; 317 varying vec3 nvec; 318 void main(void) 319 { 320 @(if (mdlopt "b") [ 321 skelanim $arg2 (mdlopt "n") 322 ] [result [ 323 #define mpos vvertex 324 #define mquat vtangent 325 @(qtangentdecode (mdlopt "n")) 326 ]]) 327 328 gl_Position = modelmatrix * mpos; 329 330 texcoord0 = vtexcoord0 + texscroll; 331 332 nvec = modelworld * mnormal; 333 } 334 ] 335] 336 337rsmmodelfragmentshader = [ 338 local modeltype 339 modeltype = $arg1 340 result [ 341 varying vec2 texcoord0; 342 varying vec3 nvec; 343 uniform vec4 colorscale; 344 @(? (mdlopt "a") [uniform float alphatest;]) 345 uniform vec3 rsmdir; 346 uniform sampler2D tex0; 347 fragdata(0, gcolor, vec4) 348 fragdata(1, gnormal, vec4) 349 void main(void) 350 { 351 vec4 diffuse = texture2D(tex0, texcoord0); 352 @(? (mdlopt "a") [ 353 if(diffuse.a <= alphatest) 354 discard; 355 ]) 356 vec3 normal = normalize(nvec); 357 @(? (mdlopt "c") [ 358 if(!gl_FrontFacing) normal = -normal; 359 ]) 360 gcolor = vec4(dot(normal, rsmdir)*diffuse.rgb*colorscale.rgb, 1.0); 361 gnormal = vec4(normal*0.5+0.5, 0.0); 362 } 363 ] 364] 365 366rsmmodelshader = [ 367 shadername = (concatword "rsmmodel" $arg1) 368 shader 0 $shadername (rsmmodelvertexshader $arg1) (rsmmodelfragmentshader $arg1) 369 loop+ i 1 4 [ 370 variantshader 0 $shadername 0 (rsmmodelvertexshader (concatword $arg1 "b") $i) [] 371 ] 372] 373 374